installer.sh.in 49 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514
  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 root, existing users, and package groups
  704. if [[ "${_gid}" -ge 1000 || "${_group}" = "_"* || "${_group}" = "root" ]]; 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 | sort -k 5)
  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 | sort -k 5)
  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 mnts="$(grep -E '^MOUNTPOINT.*swap.*$' $CONF_FILE | sort -r -k 5)"
  1070. set -- ${mnts}
  1071. while [ $# -ne 0 ]; do
  1072. local dev=$2; local fstype=$3
  1073. shift 6
  1074. if [ "$fstype" = "swap" ]; then
  1075. echo "Disabling swap space on $dev..." >$LOG
  1076. swapoff $dev >$LOG 2>&1
  1077. continue
  1078. fi
  1079. done
  1080. echo "Unmounting $TARGETDIR..." >$LOG
  1081. umount -R $TARGETDIR >$LOG 2>&1
  1082. }
  1083. log_and_count() {
  1084. local progress whole tenth
  1085. while read line; do
  1086. echo "$line" >$LOG
  1087. copy_count=$((copy_count + 1))
  1088. progress=$((1000 * copy_count / copy_total))
  1089. if [ "$progress" != "$copy_progress" ]; then
  1090. whole=$((progress / 10))
  1091. tenth=$((progress % 10))
  1092. printf "Progress: %d.%d%% (%d of %d files)\n" $whole $tenth $copy_count $copy_total
  1093. copy_progress=$progress
  1094. fi
  1095. done
  1096. }
  1097. copy_rootfs() {
  1098. local tar_in="--create --one-file-system --xattrs"
  1099. TITLE="Check $LOG for details ..."
  1100. INFOBOX "Counting files, please be patient ..." 4 60
  1101. copy_total=$(tar ${tar_in} -v -f /dev/null / 2>/dev/null | wc -l)
  1102. export copy_total copy_count=0 copy_progress=
  1103. clear
  1104. tar ${tar_in} -f - / 2>/dev/null | \
  1105. tar --extract --xattrs --xattrs-include='*' --preserve-permissions -v -f - -C $TARGETDIR | \
  1106. log_and_count | \
  1107. DIALOG --title "${TITLE}" \
  1108. --progressbox "Copying live image to target rootfs." 5 60
  1109. if [ $? -ne 0 ]; then
  1110. DIE 1
  1111. fi
  1112. unset copy_total copy_count copy_percent
  1113. }
  1114. install_packages() {
  1115. local _grub= _syspkg=
  1116. if [ -n "$EFI_SYSTEM" ]; then
  1117. if [ $EFI_FW_BITS -eq 32 ]; then
  1118. _grub="grub-i386-efi"
  1119. else
  1120. _grub="grub-x86_64-efi"
  1121. fi
  1122. else
  1123. _grub="grub"
  1124. fi
  1125. _syspkg="base-system"
  1126. mkdir -p $TARGETDIR/var/db/xbps/keys $TARGETDIR/usr/share
  1127. cp -a /usr/share/xbps.d $TARGETDIR/usr/share/
  1128. cp /var/db/xbps/keys/*.plist $TARGETDIR/var/db/xbps/keys
  1129. if [ -n "$MIRROR_DONE" ]; then
  1130. mkdir -p $TARGETDIR/etc
  1131. cp -a /etc/xbps.d $TARGETDIR/etc
  1132. fi
  1133. mkdir -p $TARGETDIR/boot/grub
  1134. _arch=$(xbps-uhelper arch)
  1135. stdbuf -oL env XBPS_ARCH=${_arch} \
  1136. xbps-install -r $TARGETDIR -SyU ${_syspkg} ${_grub} 2>&1 | \
  1137. DIALOG --title "Installing base system packages..." \
  1138. --programbox 24 80
  1139. if [ $? -ne 0 ]; then
  1140. DIE 1
  1141. fi
  1142. xbps-reconfigure -r $TARGETDIR -f base-files >/dev/null 2>&1
  1143. chroot $TARGETDIR xbps-reconfigure -a
  1144. }
  1145. enable_service() {
  1146. ln -sf /etc/sv/$1 $TARGETDIR/etc/runit/runsvdir/default/$1
  1147. }
  1148. menu_install() {
  1149. ROOTPASSWORD_DONE="$(get_option ROOTPASSWORD)"
  1150. BOOTLOADER_DONE="$(get_option BOOTLOADER)"
  1151. if [ -z "$ROOTPASSWORD_DONE" ]; then
  1152. DIALOG --msgbox "${BOLD}The root password has not been configured, \
  1153. please do so before starting the installation.${RESET}" ${MSGBOXSIZE}
  1154. return 1
  1155. elif [ -z "$BOOTLOADER_DONE" ]; then
  1156. DIALOG --msgbox "${BOLD}The disk to install the bootloader has not been \
  1157. configured, please do so before starting the installation.${RESET}" ${MSGBOXSIZE}
  1158. return 1
  1159. fi
  1160. # Validate filesystems after making sure bootloader is done,
  1161. # so that specific checks can be made based on the selection
  1162. validate_filesystems || return 1
  1163. if [ -z "$FILESYSTEMS_DONE" ]; then
  1164. DIALOG --msgbox "${BOLD}Required filesystems were not configured, \
  1165. please do so before starting the installation.${RESET}" ${MSGBOXSIZE}
  1166. return 1
  1167. fi
  1168. DIALOG --yesno "${BOLD}The following operations will be executed:${RESET}\n\n
  1169. ${BOLD}${TARGETFS}${RESET}\n
  1170. ${BOLD}${RED}WARNING: data on partitions will be COMPLETELY DESTROYED for new \
  1171. filesystems.${RESET}\n\n
  1172. ${BOLD}Do you want to continue?${RESET}" 20 80 || return
  1173. unset TARGETFS
  1174. # Create and mount filesystems
  1175. create_filesystems
  1176. # If source not set use defaults.
  1177. if [ "$(get_option SOURCE)" = "local" -o -z "$SOURCE_DONE" ]; then
  1178. copy_rootfs
  1179. . /etc/default/live.conf
  1180. rm -f $TARGETDIR/etc/motd
  1181. rm -f $TARGETDIR/etc/issue
  1182. rm -f $TARGETDIR/usr/sbin/void-installer
  1183. # Remove modified sddm.conf to let sddm use the defaults.
  1184. rm -f $TARGETDIR/etc/sddm.conf
  1185. # Remove live user.
  1186. echo "Removing $USERNAME live user from targetdir ..." >$LOG
  1187. chroot $TARGETDIR userdel -r $USERNAME >$LOG 2>&1
  1188. rm -f $TARGETDIR/etc/sudoers.d/99-void-live
  1189. sed -i "s,GETTY_ARGS=\"--noclear -a $USERNAME\",GETTY_ARGS=\"--noclear\",g" $TARGETDIR/etc/sv/agetty-tty1/conf
  1190. TITLE="Check $LOG for details ..."
  1191. INFOBOX "Rebuilding initramfs for target ..." 4 60
  1192. echo "Rebuilding initramfs for target ..." >$LOG
  1193. # mount required fs
  1194. mount_filesystems
  1195. chroot $TARGETDIR dracut --no-hostonly --add-drivers "ahci" --force >>$LOG 2>&1
  1196. INFOBOX "Removing temporary packages from target ..." 4 60
  1197. echo "Removing temporary packages from target ..." >$LOG
  1198. xbps-remove -r $TARGETDIR -Ry dialog xtools-minimal xmirror >>$LOG 2>&1
  1199. rmdir $TARGETDIR/mnt/target
  1200. else
  1201. # mount required fs
  1202. mount_filesystems
  1203. # network install, use packages.
  1204. install_packages
  1205. fi
  1206. INFOBOX "Applying installer settings..." 4 60
  1207. # copy target fstab.
  1208. install -Dm644 $TARGET_FSTAB $TARGETDIR/etc/fstab
  1209. # Mount /tmp as tmpfs.
  1210. echo "tmpfs /tmp tmpfs defaults,nosuid,nodev 0 0" >> $TARGETDIR/etc/fstab
  1211. # set up keymap, locale, timezone, hostname, root passwd and user account.
  1212. set_keymap
  1213. set_locale
  1214. set_timezone
  1215. set_hostname
  1216. set_rootpassword
  1217. set_useraccount
  1218. # Copy /etc/skel files for root.
  1219. cp $TARGETDIR/etc/skel/.[bix]* $TARGETDIR/root
  1220. # network settings for target
  1221. if [ -n "$NETWORK_DONE" ]; then
  1222. local net="$(get_option NETWORK)"
  1223. set -- ${net}
  1224. local _dev="$1" _type="$2" _ip="$3" _gw="$4" _dns1="$5" _dns2="$6"
  1225. if [ -z "$_type" ]; then
  1226. # network type empty??!!!
  1227. :
  1228. elif [ "$_type" = "dhcp" ]; then
  1229. if $(echo $_dev|egrep -q "^wl.*" 2>/dev/null); then
  1230. cp /etc/wpa_supplicant/wpa_supplicant.conf $TARGETDIR/etc/wpa_supplicant
  1231. ln -sf /etc/sv/wpa_supplicant $TARGETDIR/etc/runit/runsvdir/default/wpa_supplicant
  1232. fi
  1233. enable_service dhcpcd
  1234. elif [ -n "$_dev" -a "$_type" = "static" ]; then
  1235. # static IP through dhcpcd.
  1236. mv $TARGETDIR/etc/dhcpcd.conf $TARGETDIR/etc/dhcpcd.conf.orig
  1237. echo "# Static IP configuration set by the void-installer for $_dev." \
  1238. >$TARGETDIR/etc/dhcpcd.conf
  1239. echo "interface $_dev" >>$TARGETDIR/etc/dhcpcd.conf
  1240. echo "static ip_address=$_ip" >>$TARGETDIR/etc/dhcpcd.conf
  1241. echo "static routers=$_gw" >>$TARGETDIR/etc/dhcpcd.conf
  1242. echo "static domain_name_servers=$_dns1 $_dns2" >>$TARGETDIR/etc/dhcpcd.conf
  1243. enable_service dhcpcd
  1244. fi
  1245. fi
  1246. if [ -d $TARGETDIR/etc/sudoers.d ]; then
  1247. USERLOGIN="$(get_option USERLOGIN)"
  1248. if [ -z "$(echo $(get_option USERGROUPS) | grep -w wheel)" -a -n "$USERLOGIN" ]; then
  1249. # enable sudo for primary user USERLOGIN who is not member of wheel
  1250. echo "# Enable sudo for login '$USERLOGIN'" > "$TARGETDIR/etc/sudoers.d/$USERLOGIN"
  1251. echo "$USERLOGIN ALL=(ALL:ALL) ALL" >> "$TARGETDIR/etc/sudoers.d/$USERLOGIN"
  1252. else
  1253. # enable the sudoers entry for members of group wheel
  1254. echo "%wheel ALL=(ALL:ALL) ALL" > "$TARGETDIR/etc/sudoers.d/wheel"
  1255. fi
  1256. unset USERLOGIN
  1257. fi
  1258. # clean up polkit rule - it's only useful in live systems
  1259. rm -f $TARGETDIR/etc/polkit-1/rules.d/void-live.rules
  1260. # enable text console for grub if chosen
  1261. if [ "$(get_option TEXTCONSOLE)" = "1" ]; then
  1262. sed -i $TARGETDIR/etc/default/grub \
  1263. -e 's|#\(GRUB_TERMINAL_INPUT\).*|\1=console|' \
  1264. -e 's|#\(GRUB_TERMINAL_OUTPUT\).*|\1=console|'
  1265. fi
  1266. # install bootloader.
  1267. set_bootloader
  1268. sync && sync && sync
  1269. # unmount all filesystems.
  1270. umount_filesystems
  1271. # installed successfully.
  1272. DIALOG --yesno "${BOLD}Void Linux has been installed successfully!${RESET}\n
  1273. Do you want to reboot the system?" ${YESNOSIZE}
  1274. if [ $? -eq 0 ]; then
  1275. shutdown -r now
  1276. else
  1277. return
  1278. fi
  1279. }
  1280. menu_source() {
  1281. local src=
  1282. DIALOG --title " Select installation source " \
  1283. --menu "$MENULABEL" 8 70 0 \
  1284. "Local" "Packages from ISO image" \
  1285. "Network" "Base system only, downloaded from official repository"
  1286. case "$(cat $ANSWER)" in
  1287. "Local") src="local";;
  1288. "Network") src="net";
  1289. if [ -z "$NETWORK_DONE" ]; then
  1290. if test_network; then
  1291. menu_network
  1292. fi
  1293. fi;;
  1294. *) return 1;;
  1295. esac
  1296. SOURCE_DONE=1
  1297. set_option SOURCE $src
  1298. }
  1299. menu_mirror() {
  1300. xmirror 2>$LOG && MIRROR_DONE=1
  1301. }
  1302. menu() {
  1303. local AFTER_HOSTNAME
  1304. if [ -z "$DEFITEM" ]; then
  1305. DEFITEM="Keyboard"
  1306. fi
  1307. if xbps-uhelper arch | grep -qe '-musl$'; then
  1308. AFTER_HOSTNAME="Timezone"
  1309. DIALOG --default-item $DEFITEM \
  1310. --extra-button --extra-label "Settings" \
  1311. --title " Void Linux installation menu " \
  1312. --menu "$MENULABEL" 10 70 0 \
  1313. "Keyboard" "Set system keyboard" \
  1314. "Network" "Set up the network" \
  1315. "Source" "Set source installation" \
  1316. "Mirror" "Select XBPS mirror" \
  1317. "Hostname" "Set system hostname" \
  1318. "Timezone" "Set system time zone" \
  1319. "RootPassword" "Set system root password" \
  1320. "UserAccount" "Set primary user name and password" \
  1321. "BootLoader" "Set disk to install bootloader" \
  1322. "Partition" "Partition disk(s)" \
  1323. "Filesystems" "Configure filesystems and mount points" \
  1324. "Install" "Start installation with saved settings" \
  1325. "Exit" "Exit installation"
  1326. else
  1327. AFTER_HOSTNAME="Locale"
  1328. DIALOG --default-item $DEFITEM \
  1329. --extra-button --extra-label "Settings" \
  1330. --title " Void Linux installation menu " \
  1331. --menu "$MENULABEL" 10 70 0 \
  1332. "Keyboard" "Set system keyboard" \
  1333. "Network" "Set up the network" \
  1334. "Source" "Set source installation" \
  1335. "Mirror" "Select XBPS mirror" \
  1336. "Hostname" "Set system hostname" \
  1337. "Locale" "Set system locale" \
  1338. "Timezone" "Set system time zone" \
  1339. "RootPassword" "Set system root password" \
  1340. "UserAccount" "Set primary user name and password" \
  1341. "BootLoader" "Set disk to install bootloader" \
  1342. "Partition" "Partition disk(s)" \
  1343. "Filesystems" "Configure filesystems and mount points" \
  1344. "Install" "Start installation with saved settings" \
  1345. "Exit" "Exit installation"
  1346. fi
  1347. if [ $? -eq 3 ]; then
  1348. # Show settings
  1349. cp $CONF_FILE /tmp/conf_hidden.$$;
  1350. sed -i "s/^ROOTPASSWORD.*/ROOTPASSWORD <-hidden->/" /tmp/conf_hidden.$$
  1351. sed -i "s/^USERPASSWORD.*/USERPASSWORD <-hidden->/" /tmp/conf_hidden.$$
  1352. DIALOG --title "Saved settings for installation" --textbox /tmp/conf_hidden.$$ 14 60
  1353. rm /tmp/conf_hidden.$$
  1354. return
  1355. fi
  1356. case $(cat $ANSWER) in
  1357. "Keyboard") menu_keymap && [ -n "$KEYBOARD_DONE" ] && DEFITEM="Network";;
  1358. "Network") menu_network && [ -n "$NETWORK_DONE" ] && DEFITEM="Source";;
  1359. "Source") menu_source && [ -n "$SOURCE_DONE" ] && DEFITEM="Mirror";;
  1360. "Mirror") menu_mirror && [ -n "$MIRROR_DONE" ] && DEFITEM="Hostname";;
  1361. "Hostname") menu_hostname && [ -n "$HOSTNAME_DONE" ] && DEFITEM="$AFTER_HOSTNAME";;
  1362. "Locale") menu_locale && [ -n "$LOCALE_DONE" ] && DEFITEM="Timezone";;
  1363. "Timezone") menu_timezone && [ -n "$TIMEZONE_DONE" ] && DEFITEM="RootPassword";;
  1364. "RootPassword") menu_rootpassword && [ -n "$ROOTPASSWORD_DONE" ] && DEFITEM="UserAccount";;
  1365. "UserAccount") menu_useraccount && [ -n "$USERNAME_DONE" ] && [ -n "$USERPASSWORD_DONE" ] \
  1366. && DEFITEM="BootLoader";;
  1367. "BootLoader") menu_bootloader && [ -n "$BOOTLOADER_DONE" ] && DEFITEM="Partition";;
  1368. "Partition") menu_partitions && [ -n "$PARTITIONS_DONE" ] && DEFITEM="Filesystems";;
  1369. "Filesystems") menu_filesystems && [ -n "$FILESYSTEMS_DONE" ] && DEFITEM="Install";;
  1370. "Install") menu_install;;
  1371. "Exit") DIE;;
  1372. *) DIALOG --yesno "Abort Installation?" ${YESNOSIZE} && DIE
  1373. esac
  1374. }
  1375. if ! command -v dialog >/dev/null; then
  1376. echo "ERROR: missing dialog command, exiting..."
  1377. exit 1
  1378. fi
  1379. if [ "$(id -u)" != "0" ]; then
  1380. echo "void-installer must run as root" 1>&2
  1381. exit 1
  1382. fi
  1383. #
  1384. # main()
  1385. #
  1386. DIALOG --title "${BOLD}${RED} Enter the void ... ${RESET}" --msgbox "\n
  1387. Welcome to the Void Linux installation. A simple and minimal \
  1388. Linux distribution made from scratch and built from the source package tree \
  1389. available for XBPS, a new alternative binary package system.\n\n
  1390. The installation should be pretty straightforward. If you are in trouble \
  1391. please join us at ${BOLD}#voidlinux${RESET} on ${BOLD}irc.libera.chat${RESET}.\n\n
  1392. ${BOLD}https://www.voidlinux.org${RESET}\n\n" 16 80
  1393. while true; do
  1394. menu
  1395. done
  1396. exit 0
  1397. # vim: set ts=4 sw=4 et: