stole everything
This commit is contained in:
commit
ae1c8f14d6
14
contrib/fstab
Normal file
14
contrib/fstab
Normal file
|
@ -0,0 +1,14 @@
|
||||||
|
# /etc/fstab: static file system information.
|
||||||
|
#
|
||||||
|
# noatime turns off atimes for increased performance (atimes normally aren't
|
||||||
|
# needed); notail increases performance of ReiserFS (at the expense of storage
|
||||||
|
# efficiency). It's safe to drop the noatime options if you want and to
|
||||||
|
# switch between notail / tail freely.
|
||||||
|
#
|
||||||
|
# The root filesystem should have a pass number of either 0 or 1.
|
||||||
|
# All other filesystems should have a pass number of 0 or greater than 1.
|
||||||
|
#
|
||||||
|
# See the manpage fstab(5) for more information.
|
||||||
|
#
|
||||||
|
|
||||||
|
# <fs> <mountpoint> <type> <opts> <dump/pass>
|
489
contrib/i18n_supported
Normal file
489
contrib/i18n_supported
Normal file
|
@ -0,0 +1,489 @@
|
||||||
|
aa_DJ.UTF-8 UTF-8
|
||||||
|
aa_DJ ISO-8859-1
|
||||||
|
aa_ER UTF-8
|
||||||
|
aa_ER@saaho UTF-8
|
||||||
|
aa_ET UTF-8
|
||||||
|
af_ZA.UTF-8 UTF-8
|
||||||
|
af_ZA ISO-8859-1
|
||||||
|
agr_PE UTF-8
|
||||||
|
ak_GH UTF-8
|
||||||
|
am_ET UTF-8
|
||||||
|
an_ES.UTF-8 UTF-8
|
||||||
|
an_ES ISO-8859-15
|
||||||
|
anp_IN UTF-8
|
||||||
|
ar_AE.UTF-8 UTF-8
|
||||||
|
ar_AE ISO-8859-6
|
||||||
|
ar_BH.UTF-8 UTF-8
|
||||||
|
ar_BH ISO-8859-6
|
||||||
|
ar_DZ.UTF-8 UTF-8
|
||||||
|
ar_DZ ISO-8859-6
|
||||||
|
ar_EG.UTF-8 UTF-8
|
||||||
|
ar_EG ISO-8859-6
|
||||||
|
ar_IN UTF-8
|
||||||
|
ar_IQ.UTF-8 UTF-8
|
||||||
|
ar_IQ ISO-8859-6
|
||||||
|
ar_JO.UTF-8 UTF-8
|
||||||
|
ar_JO ISO-8859-6
|
||||||
|
ar_KW.UTF-8 UTF-8
|
||||||
|
ar_KW ISO-8859-6
|
||||||
|
ar_LB.UTF-8 UTF-8
|
||||||
|
ar_LB ISO-8859-6
|
||||||
|
ar_LY.UTF-8 UTF-8
|
||||||
|
ar_LY ISO-8859-6
|
||||||
|
ar_MA.UTF-8 UTF-8
|
||||||
|
ar_MA ISO-8859-6
|
||||||
|
ar_OM.UTF-8 UTF-8
|
||||||
|
ar_OM ISO-8859-6
|
||||||
|
ar_QA.UTF-8 UTF-8
|
||||||
|
ar_QA ISO-8859-6
|
||||||
|
ar_SA.UTF-8 UTF-8
|
||||||
|
ar_SA ISO-8859-6
|
||||||
|
ar_SD.UTF-8 UTF-8
|
||||||
|
ar_SD ISO-8859-6
|
||||||
|
ar_SS UTF-8
|
||||||
|
ar_SY.UTF-8 UTF-8
|
||||||
|
ar_SY ISO-8859-6
|
||||||
|
ar_TN.UTF-8 UTF-8
|
||||||
|
ar_TN ISO-8859-6
|
||||||
|
ar_YE.UTF-8 UTF-8
|
||||||
|
ar_YE ISO-8859-6
|
||||||
|
ayc_PE UTF-8
|
||||||
|
az_AZ UTF-8
|
||||||
|
az_IR UTF-8
|
||||||
|
as_IN UTF-8
|
||||||
|
ast_ES.UTF-8 UTF-8
|
||||||
|
ast_ES ISO-8859-15
|
||||||
|
be_BY.UTF-8 UTF-8
|
||||||
|
be_BY CP1251
|
||||||
|
be_BY@latin UTF-8
|
||||||
|
bem_ZM UTF-8
|
||||||
|
ber_DZ UTF-8
|
||||||
|
ber_MA UTF-8
|
||||||
|
bg_BG.UTF-8 UTF-8
|
||||||
|
bg_BG CP1251
|
||||||
|
bhb_IN.UTF-8 UTF-8
|
||||||
|
bho_IN UTF-8
|
||||||
|
bho_NP UTF-8
|
||||||
|
bi_VU UTF-8
|
||||||
|
bn_BD UTF-8
|
||||||
|
bn_IN UTF-8
|
||||||
|
bo_CN UTF-8
|
||||||
|
bo_IN UTF-8
|
||||||
|
br_FR.UTF-8 UTF-8
|
||||||
|
br_FR ISO-8859-1
|
||||||
|
br_FR@euro ISO-8859-15
|
||||||
|
brx_IN UTF-8
|
||||||
|
bs_BA.UTF-8 UTF-8
|
||||||
|
bs_BA ISO-8859-2
|
||||||
|
byn_ER UTF-8
|
||||||
|
C.UTF-8 UTF-8
|
||||||
|
ca_AD.UTF-8 UTF-8
|
||||||
|
ca_AD ISO-8859-15
|
||||||
|
ca_ES.UTF-8 UTF-8
|
||||||
|
ca_ES ISO-8859-1
|
||||||
|
ca_ES@euro ISO-8859-15
|
||||||
|
ca_ES@valencia UTF-8
|
||||||
|
ca_FR.UTF-8 UTF-8
|
||||||
|
ca_FR ISO-8859-15
|
||||||
|
ca_IT.UTF-8 UTF-8
|
||||||
|
ca_IT ISO-8859-15
|
||||||
|
ce_RU UTF-8
|
||||||
|
chr_US UTF-8
|
||||||
|
ckb_IQ UTF-8
|
||||||
|
cmn_TW UTF-8
|
||||||
|
crh_UA UTF-8
|
||||||
|
cs_CZ.UTF-8 UTF-8
|
||||||
|
cs_CZ ISO-8859-2
|
||||||
|
csb_PL UTF-8
|
||||||
|
cv_RU UTF-8
|
||||||
|
cy_GB.UTF-8 UTF-8
|
||||||
|
cy_GB ISO-8859-14
|
||||||
|
da_DK.UTF-8 UTF-8
|
||||||
|
da_DK ISO-8859-1
|
||||||
|
de_AT.UTF-8 UTF-8
|
||||||
|
de_AT ISO-8859-1
|
||||||
|
de_AT@euro ISO-8859-15
|
||||||
|
de_BE.UTF-8 UTF-8
|
||||||
|
de_BE ISO-8859-1
|
||||||
|
de_BE@euro ISO-8859-15
|
||||||
|
de_CH.UTF-8 UTF-8
|
||||||
|
de_CH ISO-8859-1
|
||||||
|
de_DE.UTF-8 UTF-8
|
||||||
|
de_DE ISO-8859-1
|
||||||
|
de_DE@euro ISO-8859-15
|
||||||
|
de_IT.UTF-8 UTF-8
|
||||||
|
de_IT ISO-8859-1
|
||||||
|
de_LI.UTF-8 UTF-8
|
||||||
|
de_LU.UTF-8 UTF-8
|
||||||
|
de_LU ISO-8859-1
|
||||||
|
de_LU@euro ISO-8859-15
|
||||||
|
doi_IN UTF-8
|
||||||
|
dsb_DE UTF-8
|
||||||
|
dv_MV UTF-8
|
||||||
|
dz_BT UTF-8
|
||||||
|
el_GR.UTF-8 UTF-8
|
||||||
|
el_GR ISO-8859-7
|
||||||
|
el_GR@euro ISO-8859-7
|
||||||
|
el_CY.UTF-8 UTF-8
|
||||||
|
el_CY ISO-8859-7
|
||||||
|
en_AG UTF-8
|
||||||
|
en_AU.UTF-8 UTF-8
|
||||||
|
en_AU ISO-8859-1
|
||||||
|
en_BW.UTF-8 UTF-8
|
||||||
|
en_BW ISO-8859-1
|
||||||
|
en_CA.UTF-8 UTF-8
|
||||||
|
en_CA ISO-8859-1
|
||||||
|
en_DK.UTF-8 UTF-8
|
||||||
|
en_DK ISO-8859-1
|
||||||
|
en_GB.UTF-8 UTF-8
|
||||||
|
en_GB ISO-8859-1
|
||||||
|
en_HK.UTF-8 UTF-8
|
||||||
|
en_HK ISO-8859-1
|
||||||
|
en_IE.UTF-8 UTF-8
|
||||||
|
en_IE ISO-8859-1
|
||||||
|
en_IE@euro ISO-8859-15
|
||||||
|
en_IL UTF-8
|
||||||
|
en_IN UTF-8
|
||||||
|
en_NG UTF-8
|
||||||
|
en_NZ.UTF-8 UTF-8
|
||||||
|
en_NZ ISO-8859-1
|
||||||
|
en_PH.UTF-8 UTF-8
|
||||||
|
en_PH ISO-8859-1
|
||||||
|
en_SC.UTF-8 UTF-8
|
||||||
|
en_SG.UTF-8 UTF-8
|
||||||
|
en_SG ISO-8859-1
|
||||||
|
en_US.UTF-8 UTF-8
|
||||||
|
en_US ISO-8859-1
|
||||||
|
en_ZA.UTF-8 UTF-8
|
||||||
|
en_ZA ISO-8859-1
|
||||||
|
en_ZM UTF-8
|
||||||
|
en_ZW.UTF-8 UTF-8
|
||||||
|
en_ZW ISO-8859-1
|
||||||
|
eo UTF-8
|
||||||
|
es_AR.UTF-8 UTF-8
|
||||||
|
es_AR ISO-8859-1
|
||||||
|
es_BO.UTF-8 UTF-8
|
||||||
|
es_BO ISO-8859-1
|
||||||
|
es_CL.UTF-8 UTF-8
|
||||||
|
es_CL ISO-8859-1
|
||||||
|
es_CO.UTF-8 UTF-8
|
||||||
|
es_CO ISO-8859-1
|
||||||
|
es_CR.UTF-8 UTF-8
|
||||||
|
es_CR ISO-8859-1
|
||||||
|
es_CU UTF-8
|
||||||
|
es_DO.UTF-8 UTF-8
|
||||||
|
es_DO ISO-8859-1
|
||||||
|
es_EC.UTF-8 UTF-8
|
||||||
|
es_EC ISO-8859-1
|
||||||
|
es_ES.UTF-8 UTF-8
|
||||||
|
es_ES ISO-8859-1
|
||||||
|
es_ES@euro ISO-8859-15
|
||||||
|
es_GT.UTF-8 UTF-8
|
||||||
|
es_GT ISO-8859-1
|
||||||
|
es_HN.UTF-8 UTF-8
|
||||||
|
es_HN ISO-8859-1
|
||||||
|
es_MX.UTF-8 UTF-8
|
||||||
|
es_MX ISO-8859-1
|
||||||
|
es_NI.UTF-8 UTF-8
|
||||||
|
es_NI ISO-8859-1
|
||||||
|
es_PA.UTF-8 UTF-8
|
||||||
|
es_PA ISO-8859-1
|
||||||
|
es_PE.UTF-8 UTF-8
|
||||||
|
es_PE ISO-8859-1
|
||||||
|
es_PR.UTF-8 UTF-8
|
||||||
|
es_PR ISO-8859-1
|
||||||
|
es_PY.UTF-8 UTF-8
|
||||||
|
es_PY ISO-8859-1
|
||||||
|
es_SV.UTF-8 UTF-8
|
||||||
|
es_SV ISO-8859-1
|
||||||
|
es_US.UTF-8 UTF-8
|
||||||
|
es_US ISO-8859-1
|
||||||
|
es_UY.UTF-8 UTF-8
|
||||||
|
es_UY ISO-8859-1
|
||||||
|
es_VE.UTF-8 UTF-8
|
||||||
|
es_VE ISO-8859-1
|
||||||
|
et_EE.UTF-8 UTF-8
|
||||||
|
et_EE ISO-8859-1
|
||||||
|
et_EE.ISO-8859-15 ISO-8859-15
|
||||||
|
eu_ES.UTF-8 UTF-8
|
||||||
|
eu_ES ISO-8859-1
|
||||||
|
eu_ES@euro ISO-8859-15
|
||||||
|
fa_IR UTF-8
|
||||||
|
ff_SN UTF-8
|
||||||
|
fi_FI.UTF-8 UTF-8
|
||||||
|
fi_FI ISO-8859-1
|
||||||
|
fi_FI@euro ISO-8859-15
|
||||||
|
fil_PH UTF-8
|
||||||
|
fo_FO.UTF-8 UTF-8
|
||||||
|
fo_FO ISO-8859-1
|
||||||
|
fr_BE.UTF-8 UTF-8
|
||||||
|
fr_BE ISO-8859-1
|
||||||
|
fr_BE@euro ISO-8859-15
|
||||||
|
fr_CA.UTF-8 UTF-8
|
||||||
|
fr_CA ISO-8859-1
|
||||||
|
fr_CH.UTF-8 UTF-8
|
||||||
|
fr_CH ISO-8859-1
|
||||||
|
fr_FR.UTF-8 UTF-8
|
||||||
|
fr_FR ISO-8859-1
|
||||||
|
fr_FR@euro ISO-8859-15
|
||||||
|
fr_LU.UTF-8 UTF-8
|
||||||
|
fr_LU ISO-8859-1
|
||||||
|
fr_LU@euro ISO-8859-15
|
||||||
|
fur_IT UTF-8
|
||||||
|
fy_NL UTF-8
|
||||||
|
fy_DE UTF-8
|
||||||
|
ga_IE.UTF-8 UTF-8
|
||||||
|
ga_IE ISO-8859-1
|
||||||
|
ga_IE@euro ISO-8859-15
|
||||||
|
gd_GB.UTF-8 UTF-8
|
||||||
|
gd_GB ISO-8859-15
|
||||||
|
gez_ER UTF-8
|
||||||
|
gez_ER@abegede UTF-8
|
||||||
|
gez_ET UTF-8
|
||||||
|
gez_ET@abegede UTF-8
|
||||||
|
gl_ES.UTF-8 UTF-8
|
||||||
|
gl_ES ISO-8859-1
|
||||||
|
gl_ES@euro ISO-8859-15
|
||||||
|
gu_IN UTF-8
|
||||||
|
gv_GB.UTF-8 UTF-8
|
||||||
|
gv_GB ISO-8859-1
|
||||||
|
ha_NG UTF-8
|
||||||
|
hak_TW UTF-8
|
||||||
|
he_IL.UTF-8 UTF-8
|
||||||
|
he_IL ISO-8859-8
|
||||||
|
hi_IN UTF-8
|
||||||
|
hif_FJ UTF-8
|
||||||
|
hne_IN UTF-8
|
||||||
|
hr_HR.UTF-8 UTF-8
|
||||||
|
hr_HR ISO-8859-2
|
||||||
|
hsb_DE ISO-8859-2
|
||||||
|
hsb_DE.UTF-8 UTF-8
|
||||||
|
ht_HT UTF-8
|
||||||
|
hu_HU.UTF-8 UTF-8
|
||||||
|
hu_HU ISO-8859-2
|
||||||
|
hy_AM UTF-8
|
||||||
|
hy_AM.ARMSCII-8 ARMSCII-8
|
||||||
|
ia_FR UTF-8
|
||||||
|
id_ID.UTF-8 UTF-8
|
||||||
|
id_ID ISO-8859-1
|
||||||
|
ig_NG UTF-8
|
||||||
|
ik_CA UTF-8
|
||||||
|
is_IS.UTF-8 UTF-8
|
||||||
|
is_IS ISO-8859-1
|
||||||
|
it_CH.UTF-8 UTF-8
|
||||||
|
it_CH ISO-8859-1
|
||||||
|
it_IT.UTF-8 UTF-8
|
||||||
|
it_IT ISO-8859-1
|
||||||
|
it_IT@euro ISO-8859-15
|
||||||
|
iu_CA UTF-8
|
||||||
|
ja_JP.EUC-JP EUC-JP
|
||||||
|
ja_JP.UTF-8 UTF-8
|
||||||
|
ka_GE.UTF-8 UTF-8
|
||||||
|
ka_GE GEORGIAN-PS
|
||||||
|
kab_DZ UTF-8
|
||||||
|
kk_KZ.UTF-8 UTF-8
|
||||||
|
kk_KZ PT154
|
||||||
|
kl_GL.UTF-8 UTF-8
|
||||||
|
kl_GL ISO-8859-1
|
||||||
|
km_KH UTF-8
|
||||||
|
kn_IN UTF-8
|
||||||
|
ko_KR.EUC-KR EUC-KR
|
||||||
|
ko_KR.UTF-8 UTF-8
|
||||||
|
kok_IN UTF-8
|
||||||
|
ks_IN UTF-8
|
||||||
|
ks_IN@devanagari UTF-8
|
||||||
|
ku_TR.UTF-8 UTF-8
|
||||||
|
ku_TR ISO-8859-9
|
||||||
|
kw_GB.UTF-8 UTF-8
|
||||||
|
kw_GB ISO-8859-1
|
||||||
|
ky_KG UTF-8
|
||||||
|
lb_LU UTF-8
|
||||||
|
lg_UG.UTF-8 UTF-8
|
||||||
|
lg_UG ISO-8859-10
|
||||||
|
li_BE UTF-8
|
||||||
|
li_NL UTF-8
|
||||||
|
lij_IT UTF-8
|
||||||
|
ln_CD UTF-8
|
||||||
|
lo_LA UTF-8
|
||||||
|
lt_LT.UTF-8 UTF-8
|
||||||
|
lt_LT ISO-8859-13
|
||||||
|
lv_LV.UTF-8 UTF-8
|
||||||
|
lv_LV ISO-8859-13
|
||||||
|
lzh_TW UTF-8
|
||||||
|
mag_IN UTF-8
|
||||||
|
mai_IN UTF-8
|
||||||
|
mai_NP UTF-8
|
||||||
|
mfe_MU UTF-8
|
||||||
|
mg_MG.UTF-8 UTF-8
|
||||||
|
mg_MG ISO-8859-15
|
||||||
|
mhr_RU UTF-8
|
||||||
|
mi_NZ.UTF-8 UTF-8
|
||||||
|
mi_NZ ISO-8859-13
|
||||||
|
miq_NI UTF-8
|
||||||
|
mjw_IN UTF-8
|
||||||
|
mk_MK.UTF-8 UTF-8
|
||||||
|
mk_MK ISO-8859-5
|
||||||
|
ml_IN UTF-8
|
||||||
|
mn_MN UTF-8
|
||||||
|
mni_IN UTF-8
|
||||||
|
mnw_MM UTF-8
|
||||||
|
mr_IN UTF-8
|
||||||
|
ms_MY.UTF-8 UTF-8
|
||||||
|
ms_MY ISO-8859-1
|
||||||
|
mt_MT.UTF-8 UTF-8
|
||||||
|
mt_MT ISO-8859-3
|
||||||
|
my_MM UTF-8
|
||||||
|
nan_TW UTF-8
|
||||||
|
nan_TW@latin UTF-8
|
||||||
|
nb_NO.UTF-8 UTF-8
|
||||||
|
nb_NO ISO-8859-1
|
||||||
|
nds_DE UTF-8
|
||||||
|
nds_NL UTF-8
|
||||||
|
ne_NP UTF-8
|
||||||
|
nhn_MX UTF-8
|
||||||
|
niu_NU UTF-8
|
||||||
|
niu_NZ UTF-8
|
||||||
|
nl_AW UTF-8
|
||||||
|
nl_BE.UTF-8 UTF-8
|
||||||
|
nl_BE ISO-8859-1
|
||||||
|
nl_BE@euro ISO-8859-15
|
||||||
|
nl_NL.UTF-8 UTF-8
|
||||||
|
nl_NL ISO-8859-1
|
||||||
|
nl_NL@euro ISO-8859-15
|
||||||
|
nn_NO.UTF-8 UTF-8
|
||||||
|
nn_NO ISO-8859-1
|
||||||
|
nr_ZA UTF-8
|
||||||
|
nso_ZA UTF-8
|
||||||
|
oc_FR.UTF-8 UTF-8
|
||||||
|
oc_FR ISO-8859-1
|
||||||
|
om_ET UTF-8
|
||||||
|
om_KE.UTF-8 UTF-8
|
||||||
|
om_KE ISO-8859-1
|
||||||
|
or_IN UTF-8
|
||||||
|
os_RU UTF-8
|
||||||
|
pa_IN UTF-8
|
||||||
|
pa_PK UTF-8
|
||||||
|
pap_AW UTF-8
|
||||||
|
pap_CW UTF-8
|
||||||
|
pl_PL.UTF-8 UTF-8
|
||||||
|
pl_PL ISO-8859-2
|
||||||
|
ps_AF UTF-8
|
||||||
|
pt_BR.UTF-8 UTF-8
|
||||||
|
pt_BR ISO-8859-1
|
||||||
|
pt_PT.UTF-8 UTF-8
|
||||||
|
pt_PT ISO-8859-1
|
||||||
|
pt_PT@euro ISO-8859-15
|
||||||
|
quz_PE UTF-8
|
||||||
|
raj_IN UTF-8
|
||||||
|
ro_RO.UTF-8 UTF-8
|
||||||
|
ro_RO ISO-8859-2
|
||||||
|
ru_RU.KOI8-R KOI8-R
|
||||||
|
ru_RU.UTF-8 UTF-8
|
||||||
|
ru_RU ISO-8859-5
|
||||||
|
ru_UA.UTF-8 UTF-8
|
||||||
|
ru_UA KOI8-U
|
||||||
|
rw_RW UTF-8
|
||||||
|
sa_IN UTF-8
|
||||||
|
sah_RU UTF-8
|
||||||
|
sat_IN UTF-8
|
||||||
|
sc_IT UTF-8
|
||||||
|
sd_IN UTF-8
|
||||||
|
sd_IN@devanagari UTF-8
|
||||||
|
se_NO UTF-8
|
||||||
|
sgs_LT UTF-8
|
||||||
|
shn_MM UTF-8
|
||||||
|
shs_CA UTF-8
|
||||||
|
si_LK UTF-8
|
||||||
|
sid_ET UTF-8
|
||||||
|
sk_SK.UTF-8 UTF-8
|
||||||
|
sk_SK ISO-8859-2
|
||||||
|
sl_SI.UTF-8 UTF-8
|
||||||
|
sl_SI ISO-8859-2
|
||||||
|
sm_WS UTF-8
|
||||||
|
so_DJ.UTF-8 UTF-8
|
||||||
|
so_DJ ISO-8859-1
|
||||||
|
so_ET UTF-8
|
||||||
|
so_KE.UTF-8 UTF-8
|
||||||
|
so_KE ISO-8859-1
|
||||||
|
so_SO.UTF-8 UTF-8
|
||||||
|
so_SO ISO-8859-1
|
||||||
|
sq_AL.UTF-8 UTF-8
|
||||||
|
sq_AL ISO-8859-1
|
||||||
|
sq_MK UTF-8
|
||||||
|
sr_ME UTF-8
|
||||||
|
sr_RS UTF-8
|
||||||
|
sr_RS@latin UTF-8
|
||||||
|
ss_ZA UTF-8
|
||||||
|
st_ZA.UTF-8 UTF-8
|
||||||
|
st_ZA ISO-8859-1
|
||||||
|
sv_FI.UTF-8 UTF-8
|
||||||
|
sv_FI ISO-8859-1
|
||||||
|
sv_FI@euro ISO-8859-15
|
||||||
|
sv_SE.UTF-8 UTF-8
|
||||||
|
sv_SE ISO-8859-1
|
||||||
|
sw_KE UTF-8
|
||||||
|
sw_TZ UTF-8
|
||||||
|
szl_PL UTF-8
|
||||||
|
ta_IN UTF-8
|
||||||
|
ta_LK UTF-8
|
||||||
|
tcy_IN.UTF-8 UTF-8
|
||||||
|
te_IN UTF-8
|
||||||
|
tg_TJ.UTF-8 UTF-8
|
||||||
|
tg_TJ KOI8-T
|
||||||
|
th_TH.UTF-8 UTF-8
|
||||||
|
th_TH TIS-620
|
||||||
|
the_NP UTF-8
|
||||||
|
ti_ER UTF-8
|
||||||
|
ti_ET UTF-8
|
||||||
|
tig_ER UTF-8
|
||||||
|
tk_TM UTF-8
|
||||||
|
tl_PH.UTF-8 UTF-8
|
||||||
|
tl_PH ISO-8859-1
|
||||||
|
tn_ZA UTF-8
|
||||||
|
to_TO UTF-8
|
||||||
|
tpi_PG UTF-8
|
||||||
|
tr_CY.UTF-8 UTF-8
|
||||||
|
tr_CY ISO-8859-9
|
||||||
|
tr_TR.UTF-8 UTF-8
|
||||||
|
tr_TR ISO-8859-9
|
||||||
|
ts_ZA UTF-8
|
||||||
|
tt_RU UTF-8
|
||||||
|
tt_RU@iqtelif UTF-8
|
||||||
|
ug_CN UTF-8
|
||||||
|
uk_UA.UTF-8 UTF-8
|
||||||
|
uk_UA KOI8-U
|
||||||
|
unm_US UTF-8
|
||||||
|
ur_IN UTF-8
|
||||||
|
ur_PK UTF-8
|
||||||
|
uz_UZ.UTF-8 UTF-8
|
||||||
|
uz_UZ ISO-8859-1
|
||||||
|
uz_UZ@cyrillic UTF-8
|
||||||
|
ve_ZA UTF-8
|
||||||
|
vi_VN UTF-8
|
||||||
|
wa_BE ISO-8859-1
|
||||||
|
wa_BE@euro ISO-8859-15
|
||||||
|
wa_BE.UTF-8 UTF-8
|
||||||
|
wae_CH UTF-8
|
||||||
|
wal_ET UTF-8
|
||||||
|
wo_SN UTF-8
|
||||||
|
xh_ZA.UTF-8 UTF-8
|
||||||
|
xh_ZA ISO-8859-1
|
||||||
|
yi_US.UTF-8 UTF-8
|
||||||
|
yi_US CP1255
|
||||||
|
yo_NG UTF-8
|
||||||
|
yue_HK UTF-8
|
||||||
|
yuw_PG UTF-8
|
||||||
|
zh_CN.GB18030 GB18030
|
||||||
|
zh_CN.GBK GBK
|
||||||
|
zh_CN.UTF-8 UTF-8
|
||||||
|
zh_CN GB2312
|
||||||
|
zh_HK.UTF-8 UTF-8
|
||||||
|
zh_HK BIG5-HKSCS
|
||||||
|
zh_SG.UTF-8 UTF-8
|
||||||
|
zh_SG.GBK GBK
|
||||||
|
zh_SG GB2312
|
||||||
|
zh_TW.EUC-TW EUC-TW
|
||||||
|
zh_TW.UTF-8 UTF-8
|
||||||
|
zh_TW BIG5
|
||||||
|
zu_ZA.UTF-8 UTF-8
|
||||||
|
zu_ZA ISO-8859-1
|
BIN
contrib/screenshot_configure.png
Executable file
BIN
contrib/screenshot_configure.png
Executable file
Binary file not shown.
After Width: | Height: | Size: 131 KiB |
81
contrib/sshd_config
Normal file
81
contrib/sshd_config
Normal file
|
@ -0,0 +1,81 @@
|
||||||
|
# /etc/ssh/sshd_config
|
||||||
|
#
|
||||||
|
# This is the sshd server system-wide configuration file. See
|
||||||
|
# sshd_config(5) for more information.
|
||||||
|
|
||||||
|
Port 22
|
||||||
|
#AddressFamily any
|
||||||
|
ListenAddress 0.0.0.0
|
||||||
|
ListenAddress ::
|
||||||
|
|
||||||
|
#HostKey /etc/ssh/ssh_host_rsa_key
|
||||||
|
#HostKey /etc/ssh/ssh_host_dsa_key
|
||||||
|
#HostKey /etc/ssh/ssh_host_ecdsa_key
|
||||||
|
HostKey /etc/ssh/ssh_host_ed25519_key
|
||||||
|
|
||||||
|
# Limit Host Key Algorithms
|
||||||
|
HostKeyAlgorithms ssh-ed25519-cert-v01@openssh.com,ssh-ed25519
|
||||||
|
|
||||||
|
# Limit Key Exchange Algorithms
|
||||||
|
KexAlgorithms curve25519-sha256@libssh.org,diffie-hellman-group-exchange-sha256
|
||||||
|
Ciphers chacha20-poly1305@openssh.com,aes256-gcm@openssh.com,aes128-gcm@openssh.com,aes256-ctr,aes192-ctr,aes128-ctr
|
||||||
|
MACs hmac-sha2-512-etm@openssh.com,hmac-sha2-256-etm@openssh.com,umac-128-etm@openssh.com,hmac-sha2-512,hmac-sha2-256,umac-128@openssh.com
|
||||||
|
|
||||||
|
# Logging
|
||||||
|
#SyslogFacility AUTH
|
||||||
|
LogLevel VERBOSE
|
||||||
|
|
||||||
|
#LoginGraceTime 2m
|
||||||
|
PermitRootLogin yes
|
||||||
|
#StrictModes yes
|
||||||
|
MaxAuthTries 3
|
||||||
|
MaxSessions 4
|
||||||
|
|
||||||
|
# Only allow root to login
|
||||||
|
AllowGroups root
|
||||||
|
|
||||||
|
# The default is to check both .ssh/authorized_keys and .ssh/authorized_keys2
|
||||||
|
# but this is overridden so installations will only check .ssh/authorized_keys
|
||||||
|
AuthorizedKeysFile .ssh/authorized_keys
|
||||||
|
|
||||||
|
# To disable tunneled clear text passwords, change to no here!
|
||||||
|
PasswordAuthentication no
|
||||||
|
|
||||||
|
# Change to no to disable s/key passwords
|
||||||
|
ChallengeResponseAuthentication no
|
||||||
|
|
||||||
|
# Set this to 'yes' to enable PAM authentication, account processing,
|
||||||
|
# and session processing. If this is enabled, PAM authentication will
|
||||||
|
# be allowed through the ChallengeResponseAuthentication and
|
||||||
|
# PasswordAuthentication. Depending on your PAM configuration,
|
||||||
|
# PAM authentication via ChallengeResponseAuthentication may bypass
|
||||||
|
# the setting of "PermitRootLogin without-password".
|
||||||
|
# If you just want the PAM account and session checks to run without
|
||||||
|
# PAM authentication, then enable this but set PasswordAuthentication
|
||||||
|
# and ChallengeResponseAuthentication to 'no'.
|
||||||
|
UsePAM yes
|
||||||
|
|
||||||
|
AllowAgentForwarding no
|
||||||
|
AllowTcpForwarding yes
|
||||||
|
#GatewayPorts no
|
||||||
|
#X11Forwarding no
|
||||||
|
#X11DisplayOffset 10
|
||||||
|
#X11UseLocalhost yes
|
||||||
|
#PermitTTY yes
|
||||||
|
PrintMotd no
|
||||||
|
PrintLastLog yes
|
||||||
|
TCPKeepAlive no
|
||||||
|
#UseLogin no
|
||||||
|
#PermitUserEnvironment no
|
||||||
|
Compression delayed
|
||||||
|
ClientAliveInterval 300
|
||||||
|
ClientAliveCountMax 2
|
||||||
|
#UseDNS no
|
||||||
|
#PidFile /run/sshd.pid
|
||||||
|
#MaxStartups 10:30:100
|
||||||
|
#PermitTunnel no
|
||||||
|
#ChrootDirectory none
|
||||||
|
#VersionAddendum none
|
||||||
|
|
||||||
|
# override default of no subsystems
|
||||||
|
Subsystem sftp /usr/lib64/misc/sftp-server
|
136
install
Executable file
136
install
Executable file
|
@ -0,0 +1,136 @@
|
||||||
|
#!/bin/bash
|
||||||
|
set -uo pipefail
|
||||||
|
|
||||||
|
|
||||||
|
################################################
|
||||||
|
# Initialize script environment
|
||||||
|
|
||||||
|
# Find the directory this script is stored in. (from: http://stackoverflow.com/questions/59895)
|
||||||
|
function get_source_dir() {
|
||||||
|
local source="${BASH_SOURCE[0]}"
|
||||||
|
while [[ -h $source ]]
|
||||||
|
do
|
||||||
|
local tmp
|
||||||
|
tmp="$(cd -P "$(dirname "${source}")" && pwd)"
|
||||||
|
source="$(readlink "${source}")"
|
||||||
|
[[ $source != /* ]] && source="${tmp}/${source}"
|
||||||
|
done
|
||||||
|
|
||||||
|
echo -n "$(realpath "$(dirname "${source}")")"
|
||||||
|
}
|
||||||
|
|
||||||
|
ACTUAL_WORKING_DIRECTORY="$(realpath "$(pwd)")" || exit 1
|
||||||
|
export ACTUAL_WORKING_DIRECTORY
|
||||||
|
GENTOO_INSTALL_REPO_DIR_ORIGINAL="$(get_source_dir)"
|
||||||
|
export GENTOO_INSTALL_REPO_DIR_ORIGINAL
|
||||||
|
export GENTOO_INSTALL_REPO_DIR="$GENTOO_INSTALL_REPO_DIR_ORIGINAL"
|
||||||
|
export GENTOO_INSTALL_REPO_SCRIPT_ACTIVE=true
|
||||||
|
export GENTOO_INSTALL_REPO_SCRIPT_PID=$$
|
||||||
|
|
||||||
|
umask 0077
|
||||||
|
|
||||||
|
# shellcheck source=./scripts/utils.sh
|
||||||
|
source "$GENTOO_INSTALL_REPO_DIR/scripts/utils.sh"
|
||||||
|
# shellcheck source=./scripts/config.sh
|
||||||
|
source "$GENTOO_INSTALL_REPO_DIR/scripts/config.sh"
|
||||||
|
# shellcheck source=./scripts/functions.sh
|
||||||
|
source "$GENTOO_INSTALL_REPO_DIR/scripts/functions.sh"
|
||||||
|
# shellcheck source=./scripts/main.sh
|
||||||
|
source "$GENTOO_INSTALL_REPO_DIR/scripts/main.sh"
|
||||||
|
|
||||||
|
|
||||||
|
################################################
|
||||||
|
# Main dispatch
|
||||||
|
|
||||||
|
# Instantly kill when pressing ctrl-c
|
||||||
|
trap 'kill "$GENTOO_INSTALL_REPO_SCRIPT_PID"' INT
|
||||||
|
|
||||||
|
ACTION=""
|
||||||
|
CONFIG="$GENTOO_INSTALL_REPO_DIR/gentoo.conf"
|
||||||
|
|
||||||
|
while [[ $# -gt 0 ]]; do
|
||||||
|
case "$1" in
|
||||||
|
""|"help"|"--help"|"-help"|"-h")
|
||||||
|
echo "Usage: $0 [opts]... <action>"
|
||||||
|
echo "Performs a minimal gentoo installation. See https://github.com/oddlama/gentoo-install"
|
||||||
|
echo "for more information. If the configuration file does not exist, the configurator will"
|
||||||
|
echo "be started instead."
|
||||||
|
echo ""
|
||||||
|
echo "Options:"
|
||||||
|
echo " -c, --config <CONFIG> Use the given configuration file instead of the default"
|
||||||
|
echo " location (gentoo.conf). Applies to installation as well"
|
||||||
|
echo " as initial configuration in case it doesn't exist."
|
||||||
|
echo ""
|
||||||
|
echo "Actions:"
|
||||||
|
echo " -i, --install Installs gentoo as configured. This is the default mode,"
|
||||||
|
echo " if the given configuration file exists."
|
||||||
|
echo " -R, --chroot <DIR> [CMD...] Chroot into an existing system. The root filesystem"
|
||||||
|
echo " must already be mounted under DIR. All required special"
|
||||||
|
echo " filesystems will be mounted inside, and unmounted when"
|
||||||
|
echo " the chroot exits."
|
||||||
|
exit 0
|
||||||
|
;;
|
||||||
|
"-c"|"--config")
|
||||||
|
[[ -f "$2" ]] \
|
||||||
|
|| die "Config file not found: '$2'"
|
||||||
|
CONFIG="$(cd "$ACTUAL_WORKING_DIRECTORY" && realpath --relative-to="$GENTOO_INSTALL_REPO_DIR" "$2" 2>/dev/null)" || die "Could not determine realpath to config"
|
||||||
|
shift
|
||||||
|
;;
|
||||||
|
"-R"|"--chroot")
|
||||||
|
[[ -z $ACTION ]] || die "Multiple actions given"
|
||||||
|
ACTION="chroot"
|
||||||
|
CHROOT_DIR="$2"
|
||||||
|
[[ -e "$CHROOT_DIR" ]] || die "Chroot directory not found: '$CHROOT_DIR'"
|
||||||
|
shift
|
||||||
|
;;
|
||||||
|
"-i"|"--install")
|
||||||
|
[[ -z $ACTION ]] || die "Multiple actions given"
|
||||||
|
ACTION="install"
|
||||||
|
;;
|
||||||
|
"__install_gentoo_in_chroot")
|
||||||
|
ACTION="__install_gentoo_in_chroot"
|
||||||
|
;;
|
||||||
|
*) die "Invalid option '$1'" ;;
|
||||||
|
esac
|
||||||
|
shift
|
||||||
|
done
|
||||||
|
|
||||||
|
# Check configuration location
|
||||||
|
[[ -z "${CONFIG%%"$GENTOO_INSTALL_REPO_DIR"*}" ]] \
|
||||||
|
|| die "Configuration file must be inside the installation directory. This is needed so it is accessible from within the chroot environment."
|
||||||
|
|
||||||
|
if [[ -z "$ACTION" ]]; then
|
||||||
|
if [[ -e "$CONFIG" ]]; then
|
||||||
|
# Default if configuration exists: Run installer
|
||||||
|
ACTION="install"
|
||||||
|
else
|
||||||
|
# Default if configuration does not exist: Run configurator, and exit afterwards.
|
||||||
|
echo "You have not created a gentoo.conf. Starting configurator instead of installing."
|
||||||
|
exec "$GENTOO_INSTALL_REPO_DIR/configure" "$CONFIG"
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [[ "$ACTION" != "chroot" ]]; then
|
||||||
|
# Load config if we aren't just chrooting
|
||||||
|
[[ -e "$CONFIG" ]] \
|
||||||
|
|| die "Configuration file '$CONFIG' does not exist. To run the configurator, omit '-i' flag or run ./configure"
|
||||||
|
|
||||||
|
# shellcheck disable=SC1090
|
||||||
|
source "$CONFIG" || die "Could not source config"
|
||||||
|
[[ $I_HAVE_READ_AND_EDITED_THE_CONFIG_PROPERLY == "true" ]] \
|
||||||
|
|| die "You have not properly read the config. Edit the config file and set I_HAVE_READ_AND_EDITED_THE_CONFIG_PROPERLY=true to continue."
|
||||||
|
|
||||||
|
preprocess_config
|
||||||
|
fi
|
||||||
|
|
||||||
|
[[ $EUID == 0 ]] \
|
||||||
|
|| die "Must be root"
|
||||||
|
|
||||||
|
mkdir_or_die 0755 "$TMP_DIR"
|
||||||
|
|
||||||
|
case "$ACTION" in
|
||||||
|
"chroot") main_chroot "$CHROOT_DIR" "$@" ;;
|
||||||
|
"install") main_install "$@" ;;
|
||||||
|
"__install_gentoo_in_chroot") main_install_gentoo_in_chroot "$@" ;;
|
||||||
|
*) die "Invalid action '$ACTION'" ;;
|
||||||
|
esac
|
639
scripts/config.sh
Normal file
639
scripts/config.sh
Normal file
|
@ -0,0 +1,639 @@
|
||||||
|
# shellcheck source=./scripts/protection.sh
|
||||||
|
source "$GENTOO_INSTALL_REPO_DIR/scripts/protection.sh" || exit 1
|
||||||
|
|
||||||
|
|
||||||
|
################################################
|
||||||
|
# Script internal configuration
|
||||||
|
|
||||||
|
# The temporary directory for this script,
|
||||||
|
# must reside in /tmp to allow the chrooted system to access the files
|
||||||
|
TMP_DIR="/tmp/gentoo-install"
|
||||||
|
# Mountpoint for the new system
|
||||||
|
ROOT_MOUNTPOINT="$TMP_DIR/root"
|
||||||
|
# Mountpoint for the script files for access from chroot
|
||||||
|
GENTOO_INSTALL_REPO_BIND="$TMP_DIR/bind"
|
||||||
|
# Mountpoint for the script files for access from chroot
|
||||||
|
UUID_STORAGE_DIR="$TMP_DIR/uuids"
|
||||||
|
# Backup dir for luks headers
|
||||||
|
LUKS_HEADER_BACKUP_DIR="$TMP_DIR/luks-headers"
|
||||||
|
|
||||||
|
# Flag to track usage of raid (needed to check for mdadm existence)
|
||||||
|
USED_RAID=false
|
||||||
|
# Flag to track usage of luks (needed to check for cryptsetup existence)
|
||||||
|
USED_LUKS=false
|
||||||
|
# Flag to track usage of zfs
|
||||||
|
USED_ZFS=false
|
||||||
|
# Flag to track usage of btrfs
|
||||||
|
USED_BTRFS=false
|
||||||
|
# Flag to track usage of encryption
|
||||||
|
USED_ENCRYPTION=false
|
||||||
|
# Flag to track whether partitioning or formatting is forbidden
|
||||||
|
NO_PARTITIONING_OR_FORMATTING=false
|
||||||
|
|
||||||
|
# An array of disk related actions to perform
|
||||||
|
DISK_ACTIONS=()
|
||||||
|
# An array of dracut parameters needed to boot the selected configuration
|
||||||
|
DISK_DRACUT_CMDLINE=()
|
||||||
|
# An associative array from disk id to a resolvable string
|
||||||
|
declare -gA DISK_ID_TO_RESOLVABLE
|
||||||
|
# An associative array from disk id to parent gpt disk id (only for partitions)
|
||||||
|
declare -gA DISK_ID_PART_TO_GPT_ID
|
||||||
|
# An associative array to check for existing ids (maps to uuids)
|
||||||
|
declare -gA DISK_ID_TO_UUID
|
||||||
|
# An associative set to check for correct usage of size=remaining in gpt tables
|
||||||
|
declare -gA DISK_GPT_HAD_SIZE_REMAINING
|
||||||
|
|
||||||
|
function only_one_of() {
|
||||||
|
local previous=""
|
||||||
|
local a
|
||||||
|
for a in "$@"; do
|
||||||
|
if [[ -v arguments[$a] ]]; then
|
||||||
|
if [[ -z $previous ]]; then
|
||||||
|
previous="$a"
|
||||||
|
else
|
||||||
|
die_trace 2 "Only one of the arguments ($*) can be given"
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
}
|
||||||
|
|
||||||
|
function create_new_id() {
|
||||||
|
local id="${arguments[$1]}"
|
||||||
|
[[ $id == *';'* ]] \
|
||||||
|
&& die_trace 2 "Identifier contains invalid character ';'"
|
||||||
|
[[ ! -v DISK_ID_TO_UUID[$id] ]] \
|
||||||
|
|| die_trace 2 "Identifier '$id' already exists"
|
||||||
|
DISK_ID_TO_UUID[$id]="$(load_or_generate_uuid "$(base64 -w 0 <<< "$id")")"
|
||||||
|
}
|
||||||
|
|
||||||
|
function verify_existing_id() {
|
||||||
|
local id="${arguments[$1]}"
|
||||||
|
[[ -v DISK_ID_TO_UUID[$id] ]] \
|
||||||
|
|| die_trace 2 "Identifier $1='$id' not found"
|
||||||
|
}
|
||||||
|
|
||||||
|
function verify_existing_unique_ids() {
|
||||||
|
local arg="$1"
|
||||||
|
local ids="${arguments[$arg]}"
|
||||||
|
|
||||||
|
count_orig="$(tr ';' '\n' <<< "$ids" | grep -c '\S')"
|
||||||
|
count_uniq="$(tr ';' '\n' <<< "$ids" | grep '\S' | sort -u | wc -l)"
|
||||||
|
[[ $count_orig -gt 0 ]] \
|
||||||
|
|| die_trace 2 "$arg=... must contain at least one entry"
|
||||||
|
[[ $count_orig -eq $count_uniq ]] \
|
||||||
|
|| die_trace 2 "$arg=... contains duplicate identifiers"
|
||||||
|
|
||||||
|
local id
|
||||||
|
# Splitting is intentional here
|
||||||
|
# shellcheck disable=SC2086
|
||||||
|
for id in ${ids//';'/ }; do
|
||||||
|
[[ -v DISK_ID_TO_UUID[$id] ]] \
|
||||||
|
|| die_trace 2 "$arg=... contains unknown identifier '$id'"
|
||||||
|
done
|
||||||
|
}
|
||||||
|
|
||||||
|
function verify_option() {
|
||||||
|
local opt="$1"
|
||||||
|
shift
|
||||||
|
|
||||||
|
local arg="${arguments[$opt]}"
|
||||||
|
local i
|
||||||
|
for i in "$@"; do
|
||||||
|
[[ $i == "$arg" ]] \
|
||||||
|
&& return 0
|
||||||
|
done
|
||||||
|
|
||||||
|
die_trace 2 "Invalid option $opt='$arg', must be one of ($*)"
|
||||||
|
}
|
||||||
|
|
||||||
|
# Named arguments:
|
||||||
|
# new_id: Id for the existing device
|
||||||
|
# device: The block device
|
||||||
|
function register_existing() {
|
||||||
|
local known_arguments=('+new_id' '+device')
|
||||||
|
local extra_arguments=()
|
||||||
|
declare -A arguments; parse_arguments "$@"
|
||||||
|
|
||||||
|
create_new_id new_id
|
||||||
|
local new_id="${arguments[new_id]}"
|
||||||
|
local device="${arguments[device]}"
|
||||||
|
create_resolve_entry_device "$new_id" "$device"
|
||||||
|
DISK_ACTIONS+=("action=existing" "$@" ";")
|
||||||
|
}
|
||||||
|
|
||||||
|
# Named arguments:
|
||||||
|
# new_id: Id for the new gpt table
|
||||||
|
# device|id: The operand block device or previously allocated id
|
||||||
|
function create_gpt() {
|
||||||
|
local known_arguments=('+new_id' '+device|id')
|
||||||
|
local extra_arguments=()
|
||||||
|
declare -A arguments; parse_arguments "$@"
|
||||||
|
|
||||||
|
only_one_of device id
|
||||||
|
create_new_id new_id
|
||||||
|
[[ -v arguments[id] ]] \
|
||||||
|
&& verify_existing_id id
|
||||||
|
|
||||||
|
local new_id="${arguments[new_id]}"
|
||||||
|
create_resolve_entry "$new_id" ptuuid "${DISK_ID_TO_UUID[$new_id]}"
|
||||||
|
DISK_ACTIONS+=("action=create_gpt" "$@" ";")
|
||||||
|
}
|
||||||
|
|
||||||
|
# Named arguments:
|
||||||
|
# new_id: Id for the new partition
|
||||||
|
# size: Size for the new partition, or 'remaining' to allocate the rest
|
||||||
|
# type: The parition type, either (bios, efi, swap, raid, luks, linux) (or a 4 digit hex-code for gdisk).
|
||||||
|
# id: The operand device id
|
||||||
|
function create_partition() {
|
||||||
|
local known_arguments=('+new_id' '+id' '+size' '+type')
|
||||||
|
local extra_arguments=()
|
||||||
|
declare -A arguments; parse_arguments "$@"
|
||||||
|
|
||||||
|
create_new_id new_id
|
||||||
|
verify_existing_id id
|
||||||
|
verify_option type bios efi swap raid luks linux
|
||||||
|
|
||||||
|
[[ -v "DISK_GPT_HAD_SIZE_REMAINING[${arguments[id]}]" ]] \
|
||||||
|
&& die_trace 1 "Cannot add another partition to table (${arguments[id]}) after size=remaining was used"
|
||||||
|
|
||||||
|
# shellcheck disable=SC2034
|
||||||
|
[[ ${arguments[size]} == "remaining" ]] \
|
||||||
|
&& DISK_GPT_HAD_SIZE_REMAINING[${arguments[id]}]=true
|
||||||
|
|
||||||
|
local new_id="${arguments[new_id]}"
|
||||||
|
DISK_ID_PART_TO_GPT_ID[$new_id]="${arguments[id]}"
|
||||||
|
create_resolve_entry "$new_id" partuuid "${DISK_ID_TO_UUID[$new_id]}"
|
||||||
|
DISK_ACTIONS+=("action=create_partition" "$@" ";")
|
||||||
|
}
|
||||||
|
|
||||||
|
# Named arguments:
|
||||||
|
# new_id: Id for the new raid
|
||||||
|
# level: Raid level
|
||||||
|
# name: Raid name (/dev/md/<name>)
|
||||||
|
# ids: Comma separated list of all member ids
|
||||||
|
function create_raid() {
|
||||||
|
USED_RAID=true
|
||||||
|
|
||||||
|
local known_arguments=('+new_id' '+level' '+name' '+ids')
|
||||||
|
local extra_arguments=()
|
||||||
|
declare -A arguments; parse_arguments "$@"
|
||||||
|
|
||||||
|
create_new_id new_id
|
||||||
|
verify_option level 0 1 5 6
|
||||||
|
verify_existing_unique_ids ids
|
||||||
|
|
||||||
|
local new_id="${arguments[new_id]}"
|
||||||
|
local uuid="${DISK_ID_TO_UUID[$new_id]}"
|
||||||
|
create_resolve_entry "$new_id" mdadm "$uuid"
|
||||||
|
DISK_DRACUT_CMDLINE+=("rd.md.uuid=$(uuid_to_mduuid "$uuid")")
|
||||||
|
DISK_ACTIONS+=("action=create_raid" "$@" ";")
|
||||||
|
}
|
||||||
|
|
||||||
|
# Named arguments:
|
||||||
|
# new_id: Id for the new luks
|
||||||
|
# id: The operand device id
|
||||||
|
function create_luks() {
|
||||||
|
USED_LUKS=true
|
||||||
|
USED_ENCRYPTION=true
|
||||||
|
|
||||||
|
local known_arguments=('+new_id' '+name' '+device|id')
|
||||||
|
local extra_arguments=()
|
||||||
|
declare -A arguments; parse_arguments "$@"
|
||||||
|
|
||||||
|
only_one_of device id
|
||||||
|
create_new_id new_id
|
||||||
|
[[ -v arguments[id] ]] \
|
||||||
|
&& verify_existing_id id
|
||||||
|
|
||||||
|
local new_id="${arguments[new_id]}"
|
||||||
|
local name="${arguments[name]}"
|
||||||
|
local uuid="${DISK_ID_TO_UUID[$new_id]}"
|
||||||
|
create_resolve_entry "$new_id" luks "$name"
|
||||||
|
DISK_DRACUT_CMDLINE+=("rd.luks.uuid=$uuid")
|
||||||
|
DISK_ACTIONS+=("action=create_luks" "$@" ";")
|
||||||
|
}
|
||||||
|
|
||||||
|
# Named arguments:
|
||||||
|
# new_id: Id for the new luks
|
||||||
|
# device: The device
|
||||||
|
function create_dummy() {
|
||||||
|
local known_arguments=('+new_id' '+device')
|
||||||
|
local extra_arguments=()
|
||||||
|
declare -A arguments; parse_arguments "$@"
|
||||||
|
|
||||||
|
create_new_id new_id
|
||||||
|
|
||||||
|
local new_id="${arguments[new_id]}"
|
||||||
|
local device="${arguments[device]}"
|
||||||
|
local uuid="${DISK_ID_TO_UUID[$new_id]}"
|
||||||
|
create_resolve_entry_device "$new_id" "$device"
|
||||||
|
DISK_ACTIONS+=("action=create_dummy" "$@" ";")
|
||||||
|
}
|
||||||
|
|
||||||
|
# Named arguments:
|
||||||
|
# id: Id of the device / partition created earlier
|
||||||
|
# type: One of (bios, efi, swap, ext4)
|
||||||
|
# label: The label for the formatted disk
|
||||||
|
function format() {
|
||||||
|
local known_arguments=('+id' '+type' '?label')
|
||||||
|
local extra_arguments=()
|
||||||
|
declare -A arguments; parse_arguments "$@"
|
||||||
|
|
||||||
|
verify_existing_id id
|
||||||
|
verify_option type bios efi swap ext4 btrfs
|
||||||
|
|
||||||
|
local type="${arguments[type]}"
|
||||||
|
if [[ "$type" == "btrfs" ]]; then
|
||||||
|
USED_BTRFS=true
|
||||||
|
fi
|
||||||
|
|
||||||
|
DISK_ACTIONS+=("action=format" "$@" ";")
|
||||||
|
}
|
||||||
|
|
||||||
|
# Named arguments:
|
||||||
|
# ids: List of ids for devices / partitions created earlier. Must contain at least 1 element.
|
||||||
|
# pool_type: The zfs pool type
|
||||||
|
# encrypt: Whether or not to encrypt the pool
|
||||||
|
function format_zfs() {
|
||||||
|
USED_ZFS=true
|
||||||
|
|
||||||
|
local known_arguments=('+ids' '?pool_type' '?encrypt' '?compress')
|
||||||
|
local extra_arguments=()
|
||||||
|
declare -A arguments; parse_arguments "$@"
|
||||||
|
|
||||||
|
verify_existing_unique_ids ids
|
||||||
|
|
||||||
|
USED_ENCRYPTION=${arguments[encrypt]:-false}
|
||||||
|
DISK_ACTIONS+=("action=format_zfs" "$@" ";")
|
||||||
|
}
|
||||||
|
|
||||||
|
# Named arguments:
|
||||||
|
# ids: List of ids for devices / partitions created earlier. Must contain at least 1 element.
|
||||||
|
# label: The label for the formatted disk
|
||||||
|
function format_btrfs() {
|
||||||
|
USED_BTRFS=true
|
||||||
|
|
||||||
|
local known_arguments=('+ids' '?raid_type' '?label')
|
||||||
|
local extra_arguments=()
|
||||||
|
declare -A arguments; parse_arguments "$@"
|
||||||
|
|
||||||
|
verify_existing_unique_ids ids
|
||||||
|
|
||||||
|
DISK_ACTIONS+=("action=format_btrfs" "$@" ";")
|
||||||
|
}
|
||||||
|
|
||||||
|
# Returns a comma separated list of all registered ids matching the given regex.
|
||||||
|
function expand_ids() {
|
||||||
|
local regex="$1"
|
||||||
|
for id in "${!DISK_ID_TO_UUID[@]}"; do
|
||||||
|
[[ $id =~ $regex ]] \
|
||||||
|
&& echo -n "$id;"
|
||||||
|
done
|
||||||
|
}
|
||||||
|
|
||||||
|
# Single disk, 3 partitions (efi, swap, root)
|
||||||
|
# Parameters:
|
||||||
|
# swap=<size> Create a swap partition with given size, or no swap at all if set to false.
|
||||||
|
# type=[efi|bios] Selects the boot type. Defaults to efi if not given.
|
||||||
|
# luks=[true|false] Encrypt root partition. Defaults to false if not given.
|
||||||
|
# root_fs=[ext4|btrfs] Root filesystem. Defaults to ext4 if not given.
|
||||||
|
function create_classic_single_disk_layout() {
|
||||||
|
local known_arguments=('+swap' '?type' '?luks' '?root_fs')
|
||||||
|
local extra_arguments=()
|
||||||
|
declare -A arguments; parse_arguments "$@"
|
||||||
|
|
||||||
|
[[ ${#extra_arguments[@]} -eq 1 ]] \
|
||||||
|
|| die_trace 1 "Expected exactly one positional argument (the device)"
|
||||||
|
local device="${extra_arguments[0]}"
|
||||||
|
local size_swap="${arguments[swap]}"
|
||||||
|
local type="${arguments[type]:-efi}"
|
||||||
|
local use_luks="${arguments[luks]:-false}"
|
||||||
|
local root_fs="${arguments[root_fs]:-ext4}"
|
||||||
|
|
||||||
|
create_gpt new_id=gpt device="$device"
|
||||||
|
create_partition new_id="part_$type" id=gpt size=1GiB type="$type"
|
||||||
|
[[ $size_swap != "false" ]] \
|
||||||
|
&& create_partition new_id=part_swap id=gpt size="$size_swap" type=swap
|
||||||
|
create_partition new_id=part_root id=gpt size=remaining type=linux
|
||||||
|
|
||||||
|
local root_id="part_root"
|
||||||
|
if [[ "$use_luks" == "true" ]]; then
|
||||||
|
create_luks new_id=part_luks_root name="root" id=part_root
|
||||||
|
root_id="part_luks_root"
|
||||||
|
fi
|
||||||
|
|
||||||
|
format id="part_$type" type="$type" label="$type"
|
||||||
|
[[ $size_swap != "false" ]] \
|
||||||
|
&& format id=part_swap type=swap label=swap
|
||||||
|
format id="$root_id" type="$root_fs" label=root
|
||||||
|
|
||||||
|
if [[ $type == "efi" ]]; then
|
||||||
|
DISK_ID_EFI="part_$type"
|
||||||
|
else
|
||||||
|
DISK_ID_BIOS="part_$type"
|
||||||
|
fi
|
||||||
|
[[ $size_swap != "false" ]] \
|
||||||
|
&& DISK_ID_SWAP=part_swap
|
||||||
|
DISK_ID_ROOT="$root_id"
|
||||||
|
|
||||||
|
if [[ $root_fs == "btrfs" ]]; then
|
||||||
|
DISK_ID_ROOT_TYPE="btrfs"
|
||||||
|
DISK_ID_ROOT_MOUNT_OPTS="defaults,noatime,compress-force=zstd,subvol=/root"
|
||||||
|
elif [[ $root_fs == "ext4" ]]; then
|
||||||
|
DISK_ID_ROOT_TYPE="ext4"
|
||||||
|
DISK_ID_ROOT_MOUNT_OPTS="defaults,noatime,errors=remount-ro,discard"
|
||||||
|
else
|
||||||
|
die "Unsupported root filesystem type"
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
function create_single_disk_layout() {
|
||||||
|
die "'create_single_disk_layout' is deprecated, please use 'create_classic_single_disk_layout' instead. It is fully option-compatible to the old version."
|
||||||
|
}
|
||||||
|
|
||||||
|
# Skip partitioning, and use existing pre-formatted partitions. These must be trivially mountable.
|
||||||
|
# Parameters:
|
||||||
|
# swap=<device|false> Use the given device as swap, or no swap at all if set to false.
|
||||||
|
# boot=<device> Use the given device as the bios/efi partition.
|
||||||
|
# type=[efi|bios] Selects the boot type. Defaults to efi if not given.
|
||||||
|
function create_existing_partitions_layout() {
|
||||||
|
NO_PARTITIONING_OR_FORMATTING=true
|
||||||
|
|
||||||
|
local known_arguments=('+swap' '+boot' '?type')
|
||||||
|
local extra_arguments=()
|
||||||
|
declare -A arguments; parse_arguments "$@"
|
||||||
|
|
||||||
|
[[ ${#extra_arguments[@]} -eq 1 ]] \
|
||||||
|
|| die_trace 1 "Expected exactly one positional argument (the device)"
|
||||||
|
local device="${extra_arguments[0]}"
|
||||||
|
local swap_device="${arguments[swap]}"
|
||||||
|
local boot_device="${arguments[boot]}"
|
||||||
|
local type="${arguments[type]:-efi}"
|
||||||
|
|
||||||
|
register_existing new_id="part_$type" device="$boot_device"
|
||||||
|
[[ $swap_device != "false" ]] \
|
||||||
|
&& register_existing new_id="part_swap" device="$swap_device"
|
||||||
|
register_existing new_id="part_root" device="$device"
|
||||||
|
|
||||||
|
if [[ $type == "efi" ]]; then
|
||||||
|
DISK_ID_EFI="part_$type"
|
||||||
|
else
|
||||||
|
DISK_ID_BIOS="part_$type"
|
||||||
|
fi
|
||||||
|
[[ $swap_device != "false" ]] \
|
||||||
|
&& DISK_ID_SWAP=part_swap
|
||||||
|
DISK_ID_ROOT="part_root"
|
||||||
|
DISK_ID_ROOT_TYPE="" # unknown, could be anything. Left empty to skip generating an fstab entry.
|
||||||
|
}
|
||||||
|
|
||||||
|
# Multiple disks, up to 3 partitions on first disk (efi, optional swap, root with zfs).
|
||||||
|
# Additional devices will be added to the zfs pool.
|
||||||
|
# Parameters:
|
||||||
|
# swap=<size> Create a swap partition with given size, or no swap at all if set to false.
|
||||||
|
# type=[efi|bios] Selects the boot type. Defaults to efi if not given.
|
||||||
|
# encrypt=[true|false] Encrypt zfs pool. Defaults to false if not given.
|
||||||
|
# pool_type=[stripe|mirror] Select raid type. Defaults to stripe.
|
||||||
|
function create_zfs_centric_layout() {
|
||||||
|
local known_arguments=('+swap' '?type' '?pool_type' '?encrypt' '?compress')
|
||||||
|
local extra_arguments=()
|
||||||
|
declare -A arguments; parse_arguments "$@"
|
||||||
|
|
||||||
|
[[ ${#extra_arguments[@]} -gt 0 ]] \
|
||||||
|
|| die_trace 1 "Expected at least one positional argument (the devices)"
|
||||||
|
local device="${extra_arguments[0]}"
|
||||||
|
local size_swap="${arguments[swap]}"
|
||||||
|
local pool_type="${arguments[pool_type]:-stripe}"
|
||||||
|
local type="${arguments[type]:-efi}"
|
||||||
|
local encrypt="${arguments[encrypt]:-false}"
|
||||||
|
|
||||||
|
# Create layout on first disk
|
||||||
|
create_gpt new_id="gpt_dev0" device="${extra_arguments[0]}"
|
||||||
|
create_partition new_id="part_${type}_dev0" id="gpt_dev0" size=1GiB type="$type"
|
||||||
|
[[ $size_swap != "false" ]] \
|
||||||
|
&& create_partition new_id="part_swap_dev0" id="gpt_dev0" size="$size_swap" type=swap
|
||||||
|
create_partition new_id="part_root_dev0" id="gpt_dev0" size=remaining type=linux
|
||||||
|
|
||||||
|
local root_id="part_root_dev0"
|
||||||
|
local root_ids="part_root_dev0;"
|
||||||
|
local dev_id
|
||||||
|
for i in "${!extra_arguments[@]}"; do
|
||||||
|
[[ $i != 0 ]] || continue
|
||||||
|
dev_id="root_dev$i"
|
||||||
|
create_dummy new_id="$dev_id" device="${extra_arguments[$i]}"
|
||||||
|
root_ids="${root_ids}$dev_id;"
|
||||||
|
done
|
||||||
|
|
||||||
|
format id="part_${type}_dev0" type="$type" label="$type"
|
||||||
|
[[ $size_swap != "false" ]] \
|
||||||
|
&& format id="part_swap_dev0" type=swap label=swap
|
||||||
|
format_zfs ids="$root_ids" encrypt="$encrypt" pool_type="$pool_type"
|
||||||
|
|
||||||
|
if [[ $type == "efi" ]]; then
|
||||||
|
DISK_ID_EFI="part_${type}_dev0"
|
||||||
|
else
|
||||||
|
DISK_ID_BIOS="part_${type}_dev0"
|
||||||
|
fi
|
||||||
|
[[ $size_swap != "false" ]] \
|
||||||
|
&& DISK_ID_SWAP=part_swap_dev0
|
||||||
|
DISK_ID_ROOT="$root_id"
|
||||||
|
DISK_ID_ROOT_TYPE="zfs"
|
||||||
|
}
|
||||||
|
|
||||||
|
# Multiple disks, with raid 0 and luks
|
||||||
|
# - efi: partition on all disks, but only first disk used
|
||||||
|
# - swap: raid 0 → fs
|
||||||
|
# - root: raid 0 → luks → fs
|
||||||
|
# Parameters:
|
||||||
|
# swap=<size> Create a swap partition with given size for each disk, or no swap at all if set to false.
|
||||||
|
# type=[efi|bios] Selects the boot type. Defaults to efi if not given.
|
||||||
|
# luks=[true|false] Encrypt root partition. Defaults to true if not given.
|
||||||
|
# root_fs=[ext4|btrfs] Root filesystem. Defaults to ext4 if not given.
|
||||||
|
function create_raid0_luks_layout() {
|
||||||
|
local known_arguments=('+swap' '?type' '?luks' '?root_fs')
|
||||||
|
local extra_arguments=()
|
||||||
|
declare -A arguments; parse_arguments "$@"
|
||||||
|
|
||||||
|
[[ ${#extra_arguments[@]} -gt 0 ]] \
|
||||||
|
|| die_trace 1 "Expected at least one positional argument (the devices)"
|
||||||
|
local size_swap="${arguments[swap]}"
|
||||||
|
local type="${arguments[type]:-efi}"
|
||||||
|
local use_luks="${arguments[luks]:-true}"
|
||||||
|
local root_fs="${arguments[root_fs]:-ext4}"
|
||||||
|
|
||||||
|
for i in "${!extra_arguments[@]}"; do
|
||||||
|
create_gpt new_id="gpt_dev${i}" device="${extra_arguments[$i]}"
|
||||||
|
create_partition new_id="part_${type}_dev${i}" id="gpt_dev${i}" size=1GiB type="$type"
|
||||||
|
[[ $size_swap != "false" ]] \
|
||||||
|
&& create_partition new_id="part_swap_dev${i}" id="gpt_dev${i}" size="$size_swap" type=raid
|
||||||
|
create_partition new_id="part_root_dev${i}" id="gpt_dev${i}" size=remaining type=raid
|
||||||
|
done
|
||||||
|
|
||||||
|
[[ $size_swap != "false" ]] \
|
||||||
|
&& create_raid new_id=part_raid_swap name="swap" level=0 ids="$(expand_ids '^part_swap_dev[[:digit:]]$')"
|
||||||
|
create_raid new_id=part_raid_root name="root" level=0 ids="$(expand_ids '^part_root_dev[[:digit:]]$')"
|
||||||
|
|
||||||
|
local root_id="part_raid_root"
|
||||||
|
if [[ "$use_luks" == "true" ]]; then
|
||||||
|
create_luks new_id=part_luks_root name="root" id=part_raid_root
|
||||||
|
root_id="part_luks_root"
|
||||||
|
fi
|
||||||
|
|
||||||
|
format id="part_${type}_dev0" type="$type" label="$type"
|
||||||
|
[[ $size_swap != "false" ]] \
|
||||||
|
&& format id=part_raid_swap type=swap label=swap
|
||||||
|
format id="$root_id" type="$root_fs" label=root
|
||||||
|
|
||||||
|
if [[ $type == "efi" ]]; then
|
||||||
|
DISK_ID_EFI="part_${type}_dev0"
|
||||||
|
else
|
||||||
|
DISK_ID_BIOS="part_${type}_dev0"
|
||||||
|
fi
|
||||||
|
[[ $size_swap != "false" ]] \
|
||||||
|
&& DISK_ID_SWAP=part_raid_swap
|
||||||
|
DISK_ID_ROOT="$root_id"
|
||||||
|
|
||||||
|
if [[ $root_fs == "btrfs" ]]; then
|
||||||
|
DISK_ID_ROOT_TYPE="btrfs"
|
||||||
|
DISK_ID_ROOT_MOUNT_OPTS="defaults,noatime,compress=zstd,subvol=/root"
|
||||||
|
elif [[ $root_fs == "ext4" ]]; then
|
||||||
|
DISK_ID_ROOT_TYPE="ext4"
|
||||||
|
DISK_ID_ROOT_MOUNT_OPTS="defaults,noatime,errors=remount-ro,discard"
|
||||||
|
else
|
||||||
|
die "Unsupported root filesystem type"
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
# Multiple disks, with raid 1 and luks
|
||||||
|
# - efi: partition on all disks, but only first disk used
|
||||||
|
# - swap: raid 1 → fs
|
||||||
|
# - root: raid 1 → luks → fs
|
||||||
|
# Parameters:
|
||||||
|
# swap=<size> Create a swap partition with given size for each disk, or no swap at all if set to false.
|
||||||
|
# type=[efi|bios] Selects the boot type. Defaults to efi if not given.
|
||||||
|
# luks=[true|false] Encrypt root partition. Defaults to true if not given.
|
||||||
|
# root_fs=[ext4|btrfs] Root filesystem. Defaults to ext4 if not given.
|
||||||
|
function create_raid1_luks_layout() {
|
||||||
|
local known_arguments=('+swap' '?type' '?luks' '?root_fs')
|
||||||
|
local extra_arguments=()
|
||||||
|
declare -A arguments; parse_arguments "$@"
|
||||||
|
|
||||||
|
[[ ${#extra_arguments[@]} -gt 0 ]] \
|
||||||
|
|| die_trace 1 "Expected at least one positional argument (the devices)"
|
||||||
|
local size_swap="${arguments[swap]}"
|
||||||
|
local type="${arguments[type]:-efi}"
|
||||||
|
local use_luks="${arguments[luks]:-true}"
|
||||||
|
local root_fs="${arguments[root_fs]:-ext4}"
|
||||||
|
|
||||||
|
for i in "${!extra_arguments[@]}"; do
|
||||||
|
create_gpt new_id="gpt_dev${i}" device="${extra_arguments[$i]}"
|
||||||
|
create_partition new_id="part_${type}_dev${i}" id="gpt_dev${i}" size=1GiB type="$type"
|
||||||
|
[[ $size_swap != "false" ]] \
|
||||||
|
&& create_partition new_id="part_swap_dev${i}" id="gpt_dev${i}" size="$size_swap" type=raid
|
||||||
|
create_partition new_id="part_root_dev${i}" id="gpt_dev${i}" size=remaining type=raid
|
||||||
|
done
|
||||||
|
|
||||||
|
[[ $size_swap != "false" ]] \
|
||||||
|
&& create_raid new_id=part_raid_swap name="swap" level=1 ids="$(expand_ids '^part_swap_dev[[:digit:]]$')"
|
||||||
|
create_raid new_id=part_raid_root name="root" level=1 ids="$(expand_ids '^part_root_dev[[:digit:]]$')"
|
||||||
|
|
||||||
|
local root_id="part_raid_root"
|
||||||
|
if [[ "$use_luks" == "true" ]]; then
|
||||||
|
create_luks new_id=part_luks_root name="root" id=part_raid_root
|
||||||
|
root_id="part_luks_root"
|
||||||
|
fi
|
||||||
|
|
||||||
|
format id="part_${type}_dev0" type="$type" label="$type"
|
||||||
|
[[ $size_swap != "false" ]] \
|
||||||
|
&& format id=part_raid_swap type=swap label=swap
|
||||||
|
format id="$root_id" type="$root_fs" label=root
|
||||||
|
|
||||||
|
if [[ $type == "efi" ]]; then
|
||||||
|
DISK_ID_EFI="part_${type}_dev0"
|
||||||
|
else
|
||||||
|
DISK_ID_BIOS="part_${type}_dev0"
|
||||||
|
fi
|
||||||
|
[[ $size_swap != "false" ]] \
|
||||||
|
&& DISK_ID_SWAP=part_raid_swap
|
||||||
|
DISK_ID_ROOT="$root_id"
|
||||||
|
|
||||||
|
if [[ $root_fs == "btrfs" ]]; then
|
||||||
|
DISK_ID_ROOT_TYPE="btrfs"
|
||||||
|
DISK_ID_ROOT_MOUNT_OPTS="defaults,noatime,compress=zstd,subvol=/root"
|
||||||
|
elif [[ $root_fs == "ext4" ]]; then
|
||||||
|
DISK_ID_ROOT_TYPE="ext4"
|
||||||
|
DISK_ID_ROOT_MOUNT_OPTS="defaults,noatime,errors=remount-ro,discard"
|
||||||
|
else
|
||||||
|
die "Unsupported root filesystem type"
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
# Multiple disks, up to 3 partitions on first disk (efi, optional swap, root with btrfs).
|
||||||
|
# Additional devices will be first encrypted and then put directly into btrfs array.
|
||||||
|
# Parameters:
|
||||||
|
# swap=<size> Create a swap partition with given size, or no swap at all if set to false.
|
||||||
|
# type=[efi|bios] Selects the boot type. Defaults to efi if not given.
|
||||||
|
# luks=[true|false] Encrypt root partition and btrfs devices. Defaults to false if not given.
|
||||||
|
# raid_type=[raid0|raid1] Select raid type. Defaults to raid0.
|
||||||
|
function create_btrfs_centric_layout() {
|
||||||
|
local known_arguments=('+swap' '?type' '?raid_type' '?luks')
|
||||||
|
local extra_arguments=()
|
||||||
|
declare -A arguments; parse_arguments "$@"
|
||||||
|
|
||||||
|
[[ ${#extra_arguments[@]} -gt 0 ]] \
|
||||||
|
|| die_trace 1 "Expected at least one positional argument (the devices)"
|
||||||
|
local device="${extra_arguments[0]}"
|
||||||
|
local size_swap="${arguments[swap]}"
|
||||||
|
local raid_type="${arguments[raid_type]:-raid0}"
|
||||||
|
local type="${arguments[type]:-efi}"
|
||||||
|
local use_luks="${arguments[luks]:-false}"
|
||||||
|
|
||||||
|
# Create layout on first disk
|
||||||
|
create_gpt new_id="gpt_dev0" device="${extra_arguments[0]}"
|
||||||
|
create_partition new_id="part_${type}_dev0" id="gpt_dev0" size=1GiB type="$type"
|
||||||
|
[[ $size_swap != "false" ]] \
|
||||||
|
&& create_partition new_id="part_swap_dev0" id="gpt_dev0" size="$size_swap" type=swap
|
||||||
|
create_partition new_id="part_root_dev0" id="gpt_dev0" size=remaining type=linux
|
||||||
|
|
||||||
|
local root_id
|
||||||
|
local root_ids=""
|
||||||
|
if [[ "$use_luks" == "true" ]]; then
|
||||||
|
create_luks new_id=luks_dev0 name="luks_root_0" id=part_root_dev0
|
||||||
|
root_id="luks_dev0"
|
||||||
|
root_ids="${root_ids}luks_dev0;"
|
||||||
|
for i in "${!extra_arguments[@]}"; do
|
||||||
|
[[ $i != 0 ]] || continue
|
||||||
|
create_luks new_id="luks_dev$i" name="luks_root_$i" device="${extra_arguments[$i]}"
|
||||||
|
root_ids="${root_ids}luks_dev$i;"
|
||||||
|
done
|
||||||
|
else
|
||||||
|
local dev_id=""
|
||||||
|
root_id="part_root_dev0"
|
||||||
|
root_ids="${root_ids}part_root_dev0;"
|
||||||
|
for i in "${!extra_arguments[@]}"; do
|
||||||
|
[[ $i != 0 ]] || continue
|
||||||
|
dev_id="root_dev$i"
|
||||||
|
create_dummy new_id="$dev_id" device="${extra_arguments[$i]}"
|
||||||
|
root_ids="${root_ids}$dev_id;"
|
||||||
|
done
|
||||||
|
fi
|
||||||
|
|
||||||
|
format id="part_${type}_dev0" type="$type" label="$type"
|
||||||
|
[[ $size_swap != "false" ]] \
|
||||||
|
&& format id="part_swap_dev0" type=swap label=swap
|
||||||
|
format_btrfs ids="$root_ids" label=root raid_type="$raid_type"
|
||||||
|
|
||||||
|
if [[ $type == "efi" ]]; then
|
||||||
|
DISK_ID_EFI="part_${type}_dev0"
|
||||||
|
else
|
||||||
|
DISK_ID_BIOS="part_${type}_dev0"
|
||||||
|
fi
|
||||||
|
[[ $size_swap != "false" ]] \
|
||||||
|
&& DISK_ID_SWAP=part_swap_dev0
|
||||||
|
DISK_ID_ROOT="$root_id"
|
||||||
|
DISK_ID_ROOT_TYPE="btrfs"
|
||||||
|
DISK_ID_ROOT_MOUNT_OPTS="defaults,noatime,compress=zstd,subvol=/root"
|
||||||
|
}
|
||||||
|
|
||||||
|
function create_btrfs_raid_layout() {
|
||||||
|
die "'create_btrfs_raid_layout' is deprecated, please use 'create_btrfs_centric_layout' instead. It is fully option-compatible to the old version."
|
||||||
|
}
|
26
scripts/dispatch_chroot.sh
Executable file
26
scripts/dispatch_chroot.sh
Executable file
|
@ -0,0 +1,26 @@
|
||||||
|
#!/bin/bash
|
||||||
|
set -uo pipefail
|
||||||
|
|
||||||
|
|
||||||
|
[[ $EXECUTED_IN_CHROOT != "true" ]] \
|
||||||
|
&& { echo "This script must not be executed directly!" >&2; exit 1; }
|
||||||
|
|
||||||
|
# Source the systems profile
|
||||||
|
source /etc/profile
|
||||||
|
|
||||||
|
# Set safe umask
|
||||||
|
umask 0077
|
||||||
|
|
||||||
|
# Export variables (used to determine processor count by some applications)
|
||||||
|
export NPROC="$(nproc || echo 2)"
|
||||||
|
export NPROC_ONE="$((NPROC + 1))"
|
||||||
|
|
||||||
|
# Set default makeflags and emerge flags for parallel emerges
|
||||||
|
export MAKEFLAGS="-j$NPROC"
|
||||||
|
export EMERGE_DEFAULT_OPTS="--jobs=$NPROC_ONE --load-average=$NPROC"
|
||||||
|
|
||||||
|
# Unset critical variables
|
||||||
|
unset key
|
||||||
|
|
||||||
|
# Execute the requested command
|
||||||
|
exec "$@"
|
999
scripts/functions.sh
Normal file
999
scripts/functions.sh
Normal file
|
@ -0,0 +1,999 @@
|
||||||
|
# shellcheck source=./scripts/protection.sh
|
||||||
|
source "$GENTOO_INSTALL_REPO_DIR/scripts/protection.sh" || exit 1
|
||||||
|
|
||||||
|
|
||||||
|
################################################
|
||||||
|
# Functions
|
||||||
|
|
||||||
|
function sync_time() {
|
||||||
|
einfo "Syncing time"
|
||||||
|
try ntpd -g -q
|
||||||
|
|
||||||
|
einfo "Current date: $(LANG=C date)"
|
||||||
|
einfo "Writing time to hardware clock"
|
||||||
|
hwclock --systohc --utc \
|
||||||
|
|| die "Could not save time to hardware clock"
|
||||||
|
}
|
||||||
|
|
||||||
|
function check_config() {
|
||||||
|
[[ $KEYMAP =~ ^[0-9A-Za-z-]*$ ]] \
|
||||||
|
|| die "KEYMAP contains invalid characters"
|
||||||
|
|
||||||
|
if [[ "$SYSTEMD" == "true" ]]; then
|
||||||
|
[[ "$STAGE3_BASENAME" == *systemd* ]] \
|
||||||
|
|| die "Using systemd requires a systemd stage3 archive!"
|
||||||
|
else
|
||||||
|
[[ "$STAGE3_BASENAME" != *systemd* ]] \
|
||||||
|
|| die "Using OpenRC requires a non-systemd stage3 archive!"
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Check hostname per RFC1123
|
||||||
|
local hostname_regex='^(([a-zA-Z0-9]|[a-zA-Z0-9][a-zA-Z0-9\-]*[a-zA-Z0-9])\.)*([A-Za-z0-9]|[A-Za-z0-9][A-Za-z0-9\-]*[A-Za-z0-9])$'
|
||||||
|
[[ $HOSTNAME =~ $hostname_regex ]] \
|
||||||
|
|| die "'$HOSTNAME' is not a valid hostname"
|
||||||
|
|
||||||
|
[[ -v "DISK_ID_ROOT" && -n $DISK_ID_ROOT ]] \
|
||||||
|
|| die "You must assign DISK_ID_ROOT"
|
||||||
|
[[ -v "DISK_ID_EFI" && -n $DISK_ID_EFI ]] || [[ -v "DISK_ID_BIOS" && -n $DISK_ID_BIOS ]] \
|
||||||
|
|| die "You must assign DISK_ID_EFI or DISK_ID_BIOS"
|
||||||
|
|
||||||
|
[[ -v "DISK_ID_BIOS" ]] && [[ ! -v "DISK_ID_TO_UUID[$DISK_ID_BIOS]" ]] \
|
||||||
|
&& die "Missing uuid for DISK_ID_BIOS, have you made sure it is used?"
|
||||||
|
[[ -v "DISK_ID_EFI" ]] && [[ ! -v "DISK_ID_TO_UUID[$DISK_ID_EFI]" ]] \
|
||||||
|
&& die "Missing uuid for DISK_ID_EFI, have you made sure it is used?"
|
||||||
|
[[ -v "DISK_ID_SWAP" ]] && [[ ! -v "DISK_ID_TO_UUID[$DISK_ID_SWAP]" ]] \
|
||||||
|
&& die "Missing uuid for DISK_ID_SWAP, have you made sure it is used?"
|
||||||
|
[[ -v "DISK_ID_ROOT" ]] && [[ ! -v "DISK_ID_TO_UUID[$DISK_ID_ROOT]" ]] \
|
||||||
|
&& die "Missing uuid for DISK_ID_ROOT, have you made sure it is used?"
|
||||||
|
|
||||||
|
if [[ -v "DISK_ID_EFI" ]]; then
|
||||||
|
IS_EFI=true
|
||||||
|
else
|
||||||
|
IS_EFI=false
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
function preprocess_config() {
|
||||||
|
disk_configuration
|
||||||
|
|
||||||
|
# Check encryption key if used
|
||||||
|
[[ $USED_ENCRYPTION == "true" ]] \
|
||||||
|
&& check_encryption_key
|
||||||
|
|
||||||
|
check_config
|
||||||
|
}
|
||||||
|
|
||||||
|
function prepare_installation_environment() {
|
||||||
|
maybe_exec 'before_prepare_environment'
|
||||||
|
|
||||||
|
einfo "Preparing installation environment"
|
||||||
|
|
||||||
|
local wanted_programs=(
|
||||||
|
gpg
|
||||||
|
hwclock
|
||||||
|
lsblk
|
||||||
|
ntpd
|
||||||
|
partprobe
|
||||||
|
python3
|
||||||
|
"?rhash"
|
||||||
|
sha512sum
|
||||||
|
sgdisk
|
||||||
|
uuidgen
|
||||||
|
wget
|
||||||
|
)
|
||||||
|
|
||||||
|
[[ $USED_BTRFS == "true" ]] \
|
||||||
|
&& wanted_programs+=(btrfs)
|
||||||
|
[[ $USED_ZFS == "true" ]] \
|
||||||
|
&& wanted_programs+=(zfs)
|
||||||
|
[[ $USED_RAID == "true" ]] \
|
||||||
|
&& wanted_programs+=(mdadm)
|
||||||
|
[[ $USED_LUKS == "true" ]] \
|
||||||
|
&& wanted_programs+=(cryptsetup)
|
||||||
|
|
||||||
|
# Check for existence of required programs
|
||||||
|
check_wanted_programs "${wanted_programs[@]}"
|
||||||
|
|
||||||
|
# Sync time now to prevent issues later
|
||||||
|
sync_time
|
||||||
|
|
||||||
|
maybe_exec 'after_prepare_environment'
|
||||||
|
}
|
||||||
|
|
||||||
|
function check_encryption_key() {
|
||||||
|
if [[ -z "${GENTOO_INSTALL_ENCRYPTION_KEY+set}" ]]; then
|
||||||
|
elog "You have enabled encryption, but haven't specified a key in the environment variable GENTOO_INSTALL_ENCRYPTION_KEY."
|
||||||
|
if ask "Do you want to enter an encryption key now?"; then
|
||||||
|
local encryption_key_1
|
||||||
|
local encryption_key_2
|
||||||
|
|
||||||
|
while true; do
|
||||||
|
flush_stdin
|
||||||
|
IFS="" read -s -r -p "Enter encryption key: " encryption_key_1 \
|
||||||
|
|| die "Error in read"
|
||||||
|
echo
|
||||||
|
|
||||||
|
[[ ${#encryption_key_1} -ge 8 ]] \
|
||||||
|
|| { ewarn "Your encryption key must be at least 8 characters long."; continue; }
|
||||||
|
|
||||||
|
flush_stdin
|
||||||
|
IFS="" read -s -r -p "Repeat encryption key: " encryption_key_2 \
|
||||||
|
|| die "Error in read"
|
||||||
|
echo
|
||||||
|
|
||||||
|
[[ "$encryption_key_1" == "$encryption_key_2" ]] \
|
||||||
|
|| { ewarn "Encryption keys mismatch."; continue; }
|
||||||
|
break
|
||||||
|
done
|
||||||
|
|
||||||
|
export GENTOO_INSTALL_ENCRYPTION_KEY="$encryption_key_1"
|
||||||
|
else
|
||||||
|
die "Please export GENTOO_INSTALL_ENCRYPTION_KEY with the desired key."
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
|
||||||
|
[[ ${#GENTOO_INSTALL_ENCRYPTION_KEY} -ge 8 ]] \
|
||||||
|
|| die "Your encryption key must be at least 8 characters long."
|
||||||
|
}
|
||||||
|
|
||||||
|
function add_summary_entry() {
|
||||||
|
local parent="$1"
|
||||||
|
local id="$2"
|
||||||
|
local name="$3"
|
||||||
|
local hint="$4"
|
||||||
|
local desc="$5"
|
||||||
|
|
||||||
|
local ptr
|
||||||
|
case "$id" in
|
||||||
|
"${DISK_ID_BIOS-__unused__}") ptr="[1;32m← bios[m" ;;
|
||||||
|
"${DISK_ID_EFI-__unused__}") ptr="[1;32m← efi[m" ;;
|
||||||
|
"${DISK_ID_SWAP-__unused__}") ptr="[1;34m← swap[m" ;;
|
||||||
|
"${DISK_ID_ROOT-__unused__}") ptr="[1;33m← root[m" ;;
|
||||||
|
# \x1f characters compensate for printf byte count and unicode character count mismatch due to '←'
|
||||||
|
*) ptr="[1;32m[m$(echo -e "\x1f\x1f")" ;;
|
||||||
|
esac
|
||||||
|
|
||||||
|
summary_tree[$parent]+=";$id"
|
||||||
|
summary_name[$id]="$name"
|
||||||
|
summary_hint[$id]="$hint"
|
||||||
|
summary_ptr[$id]="$ptr"
|
||||||
|
summary_desc[$id]="$desc"
|
||||||
|
}
|
||||||
|
|
||||||
|
function summary_color_args() {
|
||||||
|
for arg in "$@"; do
|
||||||
|
if [[ -v "arguments[$arg]" ]]; then
|
||||||
|
printf '%-28s ' "[1;34m$arg[2m=[m${arguments[$arg]}"
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
}
|
||||||
|
|
||||||
|
function disk_existing() {
|
||||||
|
local new_id="${arguments[new_id]}"
|
||||||
|
if [[ ${disk_action_summarize_only-false} == "true" ]]; then
|
||||||
|
add_summary_entry __root__ "$new_id" "${arguments[device]}" "(no-format, existing)" ""
|
||||||
|
fi
|
||||||
|
# no-op;
|
||||||
|
}
|
||||||
|
|
||||||
|
function disk_create_gpt() {
|
||||||
|
local new_id="${arguments[new_id]}"
|
||||||
|
if [[ ${disk_action_summarize_only-false} == "true" ]]; then
|
||||||
|
if [[ -v arguments[id] ]]; then
|
||||||
|
add_summary_entry "${arguments[id]}" "$new_id" "gpt" "" ""
|
||||||
|
else
|
||||||
|
add_summary_entry __root__ "$new_id" "${arguments[device]}" "(gpt)" ""
|
||||||
|
fi
|
||||||
|
return 0
|
||||||
|
fi
|
||||||
|
|
||||||
|
local device
|
||||||
|
local device_desc=""
|
||||||
|
if [[ -v arguments[id] ]]; then
|
||||||
|
device="$(resolve_device_by_id "${arguments[id]}")"
|
||||||
|
device_desc="$device ($id)"
|
||||||
|
else
|
||||||
|
device="${arguments[device]}"
|
||||||
|
device_desc="$device"
|
||||||
|
fi
|
||||||
|
|
||||||
|
local ptuuid="${DISK_ID_TO_UUID[$new_id]}"
|
||||||
|
|
||||||
|
einfo "Creating new gpt partition table ($new_id) on $device_desc"
|
||||||
|
wipefs --quiet --all --force "$device" \
|
||||||
|
|| die "Could not erase previous file system signatures from '$device'"
|
||||||
|
sgdisk -Z -U "$ptuuid" "$device" >/dev/null \
|
||||||
|
|| die "Could not create new gpt partition table ($new_id) on '$device'"
|
||||||
|
partprobe "$device"
|
||||||
|
}
|
||||||
|
|
||||||
|
function disk_create_partition() {
|
||||||
|
local new_id="${arguments[new_id]}"
|
||||||
|
local id="${arguments[id]}"
|
||||||
|
local size="${arguments[size]}"
|
||||||
|
local type="${arguments[type]}"
|
||||||
|
if [[ ${disk_action_summarize_only-false} == "true" ]]; then
|
||||||
|
add_summary_entry "$id" "$new_id" "part" "($type)" "$(summary_color_args size)"
|
||||||
|
return 0
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [[ $size == "remaining" ]]; then
|
||||||
|
arg_size=0
|
||||||
|
else
|
||||||
|
arg_size="+$size"
|
||||||
|
fi
|
||||||
|
|
||||||
|
local device
|
||||||
|
device="$(resolve_device_by_id "$id")" \
|
||||||
|
|| die "Could not resolve device with id=$id"
|
||||||
|
local partuuid="${DISK_ID_TO_UUID[$new_id]}"
|
||||||
|
local extra_args=""
|
||||||
|
case "$type" in
|
||||||
|
'bios') type='ef02' extra_args='--attributes=0:set:2';;
|
||||||
|
'efi') type='ef00' ;;
|
||||||
|
'swap') type='8200' ;;
|
||||||
|
'raid') type='fd00' ;;
|
||||||
|
'luks') type='8309' ;;
|
||||||
|
'linux') type='8300' ;;
|
||||||
|
*) ;;
|
||||||
|
esac
|
||||||
|
|
||||||
|
einfo "Creating partition ($new_id) with type=$type, size=$size on $device"
|
||||||
|
# shellcheck disable=SC2086
|
||||||
|
sgdisk -n "0:0:$arg_size" -t "0:$type" -u "0:$partuuid" $extra_args "$device" >/dev/null \
|
||||||
|
|| die "Could not create new gpt partition ($new_id) on '$device' ($id)"
|
||||||
|
partprobe "$device"
|
||||||
|
|
||||||
|
# On some system, we need to wait a bit for the partition to show up.
|
||||||
|
local new_device
|
||||||
|
new_device="$(resolve_device_by_id "$new_id")" \
|
||||||
|
|| die "Could not resolve new device with id=$new_id"
|
||||||
|
for i in {1..10}; do
|
||||||
|
[[ -e "$new_device" ]] && break
|
||||||
|
[[ "$i" -eq 1 ]] && printf "Waiting for partition (%s) to appear..." "$new_device"
|
||||||
|
printf " %s" "$((10 - i + 1))"
|
||||||
|
sleep 1
|
||||||
|
[[ "$i" -eq 10 ]] && echo
|
||||||
|
done
|
||||||
|
}
|
||||||
|
|
||||||
|
function disk_create_raid() {
|
||||||
|
local new_id="${arguments[new_id]}"
|
||||||
|
local level="${arguments[level]}"
|
||||||
|
local name="${arguments[name]}"
|
||||||
|
local ids="${arguments[ids]}"
|
||||||
|
if [[ ${disk_action_summarize_only-false} == "true" ]]; then
|
||||||
|
local id
|
||||||
|
# Splitting is intentional here
|
||||||
|
# shellcheck disable=SC2086
|
||||||
|
for id in ${ids//';'/ }; do
|
||||||
|
add_summary_entry "$id" "_$new_id" "raid$level" "" "$(summary_color_args name)"
|
||||||
|
done
|
||||||
|
|
||||||
|
add_summary_entry __root__ "$new_id" "raid$level" "" "$(summary_color_args name)"
|
||||||
|
return 0
|
||||||
|
fi
|
||||||
|
|
||||||
|
local devices_desc=""
|
||||||
|
local devices=()
|
||||||
|
local id
|
||||||
|
local dev
|
||||||
|
# Splitting is intentional here
|
||||||
|
# shellcheck disable=SC2086
|
||||||
|
for id in ${ids//';'/ }; do
|
||||||
|
dev="$(resolve_device_by_id "$id")" \
|
||||||
|
|| die "Could not resolve device with id=$id"
|
||||||
|
devices+=("$dev")
|
||||||
|
devices_desc+="$dev ($id), "
|
||||||
|
done
|
||||||
|
devices_desc="${devices_desc:0:-2}"
|
||||||
|
|
||||||
|
local mddevice="/dev/md/$name"
|
||||||
|
local uuid="${DISK_ID_TO_UUID[$new_id]}"
|
||||||
|
|
||||||
|
extra_args=()
|
||||||
|
if [[ ${level} == 1 ]]; then
|
||||||
|
extra_args+=("--metadata=1.0")
|
||||||
|
else
|
||||||
|
extra_args+=("--metadata=1.2")
|
||||||
|
fi
|
||||||
|
|
||||||
|
einfo "Creating raid$level ($new_id) on $devices_desc"
|
||||||
|
mdadm \
|
||||||
|
--create "$mddevice" \
|
||||||
|
--verbose \
|
||||||
|
--homehost="$HOSTNAME" \
|
||||||
|
"${extra_args[@]}" \
|
||||||
|
--raid-devices="${#devices[@]}" \
|
||||||
|
--uuid="$uuid" \
|
||||||
|
--level="$level" \
|
||||||
|
"${devices[@]}" \
|
||||||
|
|| die "Could not create raid$level array '$mddevice' ($new_id) on $devices_desc"
|
||||||
|
}
|
||||||
|
|
||||||
|
function disk_create_luks() {
|
||||||
|
local new_id="${arguments[new_id]}"
|
||||||
|
local name="${arguments[name]}"
|
||||||
|
if [[ ${disk_action_summarize_only-false} == "true" ]]; then
|
||||||
|
if [[ -v arguments[id] ]]; then
|
||||||
|
add_summary_entry "${arguments[id]}" "$new_id" "luks" "" ""
|
||||||
|
else
|
||||||
|
add_summary_entry __root__ "$new_id" "${arguments[device]}" "(luks)" ""
|
||||||
|
fi
|
||||||
|
return 0
|
||||||
|
fi
|
||||||
|
|
||||||
|
local device
|
||||||
|
local device_desc=""
|
||||||
|
if [[ -v arguments[id] ]]; then
|
||||||
|
device="$(resolve_device_by_id "${arguments[id]}")"
|
||||||
|
device_desc="$device ($id)"
|
||||||
|
else
|
||||||
|
device="${arguments[device]}"
|
||||||
|
device_desc="$device"
|
||||||
|
fi
|
||||||
|
|
||||||
|
local uuid="${DISK_ID_TO_UUID[$new_id]}"
|
||||||
|
|
||||||
|
einfo "Creating luks ($new_id) on $device_desc"
|
||||||
|
cryptsetup luksFormat \
|
||||||
|
--type luks2 \
|
||||||
|
--uuid "$uuid" \
|
||||||
|
--key-file <(echo -n "$GENTOO_INSTALL_ENCRYPTION_KEY") \
|
||||||
|
--cipher aes-xts-plain64 \
|
||||||
|
--hash sha512 \
|
||||||
|
--pbkdf argon2id \
|
||||||
|
--iter-time 4000 \
|
||||||
|
--key-size 512 \
|
||||||
|
--batch-mode \
|
||||||
|
"$device" \
|
||||||
|
|| die "Could not create luks on $device_desc"
|
||||||
|
mkdir -p "$LUKS_HEADER_BACKUP_DIR" \
|
||||||
|
|| die "Could not create luks header backup dir '$LUKS_HEADER_BACKUP_DIR'"
|
||||||
|
local header_file="$LUKS_HEADER_BACKUP_DIR/luks-header-$id-${uuid,,}.img"
|
||||||
|
[[ ! -e $header_file ]] \
|
||||||
|
|| rm "$header_file" \
|
||||||
|
|| die "Could not remove old luks header backup file '$header_file'"
|
||||||
|
cryptsetup luksHeaderBackup "$device" \
|
||||||
|
--header-backup-file "$header_file" \
|
||||||
|
|| die "Could not backup luks header on $device_desc"
|
||||||
|
cryptsetup open --type luks2 \
|
||||||
|
--key-file <(echo -n "$GENTOO_INSTALL_ENCRYPTION_KEY") \
|
||||||
|
"$device" "$name" \
|
||||||
|
|| die "Could not open luks encrypted device $device_desc"
|
||||||
|
}
|
||||||
|
|
||||||
|
function disk_create_dummy() {
|
||||||
|
local new_id="${arguments[new_id]}"
|
||||||
|
local device="${arguments[device]}"
|
||||||
|
if [[ ${disk_action_summarize_only-false} == "true" ]]; then
|
||||||
|
add_summary_entry __root__ "$new_id" "$device" "" ""
|
||||||
|
return 0
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
function init_btrfs() {
|
||||||
|
local device="$1"
|
||||||
|
local desc="$2"
|
||||||
|
mkdir -p /btrfs \
|
||||||
|
|| die "Could not create /btrfs directory"
|
||||||
|
mount "$device" /btrfs \
|
||||||
|
|| die "Could not mount $desc to /btrfs"
|
||||||
|
btrfs subvolume create /btrfs/root \
|
||||||
|
|| die "Could not create btrfs subvolume /root on $desc"
|
||||||
|
btrfs subvolume set-default /btrfs/root \
|
||||||
|
|| die "Could not set default btrfs subvolume to /root on $desc"
|
||||||
|
umount /btrfs \
|
||||||
|
|| die "Could not unmount btrfs on $desc"
|
||||||
|
}
|
||||||
|
|
||||||
|
function disk_format() {
|
||||||
|
local id="${arguments[id]}"
|
||||||
|
local type="${arguments[type]}"
|
||||||
|
local label="${arguments[label]}"
|
||||||
|
if [[ ${disk_action_summarize_only-false} == "true" ]]; then
|
||||||
|
add_summary_entry "${arguments[id]}" "__fs__${arguments[id]}" "${arguments[type]}" "(fs)" "$(summary_color_args label)"
|
||||||
|
return 0
|
||||||
|
fi
|
||||||
|
|
||||||
|
local device
|
||||||
|
device="$(resolve_device_by_id "$id")" \
|
||||||
|
|| die "Could not resolve device with id=$id"
|
||||||
|
|
||||||
|
einfo "Formatting $device ($id) with $type"
|
||||||
|
wipefs --quiet --all --force "$device" \
|
||||||
|
|| die "Could not erase previous file system signatures from '$device' ($id)"
|
||||||
|
|
||||||
|
case "$type" in
|
||||||
|
'bios'|'efi')
|
||||||
|
if [[ -v "arguments[label]" ]]; then
|
||||||
|
mkfs.fat -F 32 -n "$label" "$device" \
|
||||||
|
|| die "Could not format device '$device' ($id)"
|
||||||
|
else
|
||||||
|
mkfs.fat -F 32 "$device" \
|
||||||
|
|| die "Could not format device '$device' ($id)"
|
||||||
|
fi
|
||||||
|
;;
|
||||||
|
'swap')
|
||||||
|
if [[ -v "arguments[label]" ]]; then
|
||||||
|
mkswap -L "$label" "$device" \
|
||||||
|
|| die "Could not format device '$device' ($id)"
|
||||||
|
else
|
||||||
|
mkswap "$device" \
|
||||||
|
|| die "Could not format device '$device' ($id)"
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Try to swapoff in case the system enabled swap automatically
|
||||||
|
swapoff "$device" &>/dev/null
|
||||||
|
;;
|
||||||
|
'ext4')
|
||||||
|
if [[ -v "arguments[label]" ]]; then
|
||||||
|
mkfs.ext4 -q -L "$label" "$device" \
|
||||||
|
|| die "Could not format device '$device' ($id)"
|
||||||
|
else
|
||||||
|
mkfs.ext4 -q "$device" \
|
||||||
|
|| die "Could not format device '$device' ($id)"
|
||||||
|
fi
|
||||||
|
;;
|
||||||
|
'btrfs')
|
||||||
|
if [[ -v "arguments[label]" ]]; then
|
||||||
|
mkfs.btrfs -q -L "$label" "$device" \
|
||||||
|
|| die "Could not format device '$device' ($id)"
|
||||||
|
else
|
||||||
|
mkfs.btrfs -q "$device" \
|
||||||
|
|| die "Could not format device '$device' ($id)"
|
||||||
|
fi
|
||||||
|
|
||||||
|
init_btrfs "$device" "'$device' ($id)"
|
||||||
|
;;
|
||||||
|
*) die "Unknown filesystem type" ;;
|
||||||
|
esac
|
||||||
|
}
|
||||||
|
|
||||||
|
# This function will be called when a custom zfs pool type has been chosen.
|
||||||
|
# $1: either 'true' or 'false' determining if the datasets should be encrypted
|
||||||
|
# $2: either 'false' or a value determining the dataset compression algorithm
|
||||||
|
# $3: a string describing all device paths (for error messages)
|
||||||
|
# $@: device paths
|
||||||
|
function format_zfs_standard() {
|
||||||
|
local encrypt="$1"
|
||||||
|
local compress="$2"
|
||||||
|
local device_desc="$3"
|
||||||
|
shift 3
|
||||||
|
local devices=("$@")
|
||||||
|
local extra_args=()
|
||||||
|
|
||||||
|
einfo "Creating zfs pool on $devices_desc"
|
||||||
|
|
||||||
|
local zfs_stdin=""
|
||||||
|
if [[ "$encrypt" == true ]]; then
|
||||||
|
extra_args+=(
|
||||||
|
"-O" "encryption=aes-256-gcm"
|
||||||
|
"-O" "keyformat=passphrase"
|
||||||
|
"-O" "keylocation=prompt"
|
||||||
|
)
|
||||||
|
|
||||||
|
zfs_stdin="$GENTOO_INSTALL_ENCRYPTION_KEY"
|
||||||
|
fi
|
||||||
|
|
||||||
|
# dnodesize=legacy might be needed for GRUB2, but auto is preferred for xattr=sa.
|
||||||
|
zpool create \
|
||||||
|
-R "$ROOT_MOUNTPOINT" \
|
||||||
|
-o ashift=12 \
|
||||||
|
-O acltype=posix \
|
||||||
|
-O atime=off \
|
||||||
|
-O xattr=sa \
|
||||||
|
-O dnodesize=auto \
|
||||||
|
-O mountpoint=none \
|
||||||
|
-O canmount=noauto \
|
||||||
|
-O devices=off \
|
||||||
|
"${extra_args[@]}" \
|
||||||
|
rpool \
|
||||||
|
"${devices[@]}" \
|
||||||
|
<<< "$zfs_stdin" \
|
||||||
|
|| die "Could not create zfs pool on $devices_desc"
|
||||||
|
|
||||||
|
if [[ "$compress" != false ]]; then
|
||||||
|
zfs set "compression=$compress" rpool \
|
||||||
|
|| die "Could enable compression on dataset 'rpool'"
|
||||||
|
fi
|
||||||
|
zfs create rpool/ROOT \
|
||||||
|
|| die "Could not create zfs dataset 'rpool/ROOT'"
|
||||||
|
zfs create -o mountpoint=/ rpool/ROOT/default \
|
||||||
|
|| die "Could not create zfs dataset 'rpool/ROOT/default'"
|
||||||
|
zpool set bootfs=rpool/ROOT/default rpool \
|
||||||
|
|| die "Could not set zfs property bootfs on rpool"
|
||||||
|
}
|
||||||
|
|
||||||
|
function disk_format_zfs() {
|
||||||
|
local ids="${arguments[ids]}"
|
||||||
|
local pool_type="${arguments[pool_type]}"
|
||||||
|
local encrypt="${arguments[encrypt]-false}"
|
||||||
|
local compress="${arguments[compress]-false}"
|
||||||
|
if [[ ${disk_action_summarize_only-false} == "true" ]]; then
|
||||||
|
local id
|
||||||
|
# Splitting is intentional here
|
||||||
|
# shellcheck disable=SC2086
|
||||||
|
for id in ${ids//';'/ }; do
|
||||||
|
add_summary_entry "$id" "__fs__$id" "zfs" "(fs)" "$(summary_color_args label)"
|
||||||
|
done
|
||||||
|
return 0
|
||||||
|
fi
|
||||||
|
|
||||||
|
local devices_desc=""
|
||||||
|
local devices=()
|
||||||
|
local id
|
||||||
|
local dev
|
||||||
|
# Splitting is intentional here
|
||||||
|
# shellcheck disable=SC2086
|
||||||
|
for id in ${ids//';'/ }; do
|
||||||
|
dev="$(resolve_device_by_id "$id")" \
|
||||||
|
|| die "Could not resolve device with id=$id"
|
||||||
|
devices+=("$dev")
|
||||||
|
devices_desc+="$dev ($id), "
|
||||||
|
done
|
||||||
|
devices_desc="${devices_desc:0:-2}"
|
||||||
|
|
||||||
|
wipefs --quiet --all --force "${devices[@]}" \
|
||||||
|
|| die "Could not erase previous file system signatures from $devices_desc"
|
||||||
|
|
||||||
|
if [[ "$pool_type" == "custom" ]]; then
|
||||||
|
format_zfs_custom "$devices_desc" "${devices[@]}"
|
||||||
|
else
|
||||||
|
format_zfs_standard "$encrypt" "$compress" "$devices_desc" "${devices[@]}"
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
function disk_format_btrfs() {
|
||||||
|
local ids="${arguments[ids]}"
|
||||||
|
local label="${arguments[label]}"
|
||||||
|
local raid_type="${arguments[raid_type]}"
|
||||||
|
if [[ ${disk_action_summarize_only-false} == "true" ]]; then
|
||||||
|
local id
|
||||||
|
# Splitting is intentional here
|
||||||
|
# shellcheck disable=SC2086
|
||||||
|
for id in ${ids//';'/ }; do
|
||||||
|
add_summary_entry "$id" "__fs__$id" "btrfs" "(fs)" "$(summary_color_args label)"
|
||||||
|
done
|
||||||
|
return 0
|
||||||
|
fi
|
||||||
|
|
||||||
|
local devices_desc=""
|
||||||
|
local devices=()
|
||||||
|
local id
|
||||||
|
local dev
|
||||||
|
# Splitting is intentional here
|
||||||
|
# shellcheck disable=SC2086
|
||||||
|
for id in ${ids//';'/ }; do
|
||||||
|
dev="$(resolve_device_by_id "$id")" \
|
||||||
|
|| die "Could not resolve device with id=$id"
|
||||||
|
devices+=("$dev")
|
||||||
|
devices_desc+="$dev ($id), "
|
||||||
|
done
|
||||||
|
devices_desc="${devices_desc:0:-2}"
|
||||||
|
|
||||||
|
wipefs --quiet --all --force "${devices[@]}" \
|
||||||
|
|| die "Could not erase previous file system signatures from $devices_desc"
|
||||||
|
|
||||||
|
# Collect extra arguments
|
||||||
|
extra_args=()
|
||||||
|
if [[ "${#devices}" -gt 1 ]] && [[ -v "arguments[raid_type]" ]]; then
|
||||||
|
extra_args+=("-d" "$raid_type")
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [[ -v "arguments[label]" ]]; then
|
||||||
|
extra_args+=("-L" "$label")
|
||||||
|
fi
|
||||||
|
|
||||||
|
einfo "Creating btrfs on $devices_desc"
|
||||||
|
mkfs.btrfs -q "${extra_args[@]}" "${devices[@]}" \
|
||||||
|
|| die "Could not create btrfs on $devices_desc"
|
||||||
|
|
||||||
|
init_btrfs "${devices[0]}" "btrfs array ($devices_desc)"
|
||||||
|
}
|
||||||
|
|
||||||
|
function apply_disk_action() {
|
||||||
|
unset known_arguments
|
||||||
|
unset arguments; declare -A arguments; parse_arguments "$@"
|
||||||
|
case "${arguments[action]}" in
|
||||||
|
'existing') disk_existing ;;
|
||||||
|
'create_gpt') disk_create_gpt ;;
|
||||||
|
'create_partition') disk_create_partition ;;
|
||||||
|
'create_raid') disk_create_raid ;;
|
||||||
|
'create_luks') disk_create_luks ;;
|
||||||
|
'create_dummy') disk_create_dummy ;;
|
||||||
|
'format') disk_format ;;
|
||||||
|
'format_zfs') disk_format_zfs ;;
|
||||||
|
'format_btrfs') disk_format_btrfs ;;
|
||||||
|
*) echo "Ignoring invalid action: ${arguments[action]}" ;;
|
||||||
|
esac
|
||||||
|
}
|
||||||
|
|
||||||
|
function print_summary_tree_entry() {
|
||||||
|
local indent_chars=""
|
||||||
|
local indent="0"
|
||||||
|
local d="1"
|
||||||
|
local maxd="$((depth - 1))"
|
||||||
|
while [[ $d -lt $maxd ]]; do
|
||||||
|
if [[ ${summary_depth_continues[$d]} == "true" ]]; then
|
||||||
|
indent_chars+='│ '
|
||||||
|
else
|
||||||
|
indent_chars+=' '
|
||||||
|
fi
|
||||||
|
indent=$((indent + 2))
|
||||||
|
d="$((d + 1))"
|
||||||
|
done
|
||||||
|
if [[ $maxd -gt 0 ]]; then
|
||||||
|
if [[ ${summary_depth_continues[$maxd]} == "true" ]]; then
|
||||||
|
indent_chars+='├─'
|
||||||
|
else
|
||||||
|
indent_chars+='└─'
|
||||||
|
fi
|
||||||
|
indent=$((indent + 2))
|
||||||
|
fi
|
||||||
|
|
||||||
|
local name="${summary_name[$root]}"
|
||||||
|
local hint="${summary_hint[$root]}"
|
||||||
|
local desc="${summary_desc[$root]}"
|
||||||
|
local ptr="${summary_ptr[$root]}"
|
||||||
|
local id_name="[2m[m"
|
||||||
|
if [[ $root != __* ]]; then
|
||||||
|
if [[ $root == _* ]]; then
|
||||||
|
id_name="[2m${root:1}[m"
|
||||||
|
else
|
||||||
|
id_name="[2m${root}[m"
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
|
||||||
|
local align=0
|
||||||
|
if [[ $indent -lt 33 ]]; then
|
||||||
|
align="$((33 - indent))"
|
||||||
|
fi
|
||||||
|
|
||||||
|
elog "$indent_chars$(printf "%-${align}s %-47s %s" \
|
||||||
|
"$name [2m$hint[m" \
|
||||||
|
"$id_name $ptr" \
|
||||||
|
"$desc")"
|
||||||
|
}
|
||||||
|
|
||||||
|
function print_summary_tree() {
|
||||||
|
local root="$1"
|
||||||
|
local depth="$((depth + 1))"
|
||||||
|
local has_children=false
|
||||||
|
|
||||||
|
if [[ -v "summary_tree[$root]" ]]; then
|
||||||
|
local children="${summary_tree[$root]}"
|
||||||
|
has_children=true
|
||||||
|
summary_depth_continues[$depth]=true
|
||||||
|
else
|
||||||
|
summary_depth_continues[$depth]=false
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [[ $root != __root__ ]]; then
|
||||||
|
print_summary_tree_entry "$root"
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [[ $has_children == "true" ]]; then
|
||||||
|
local count
|
||||||
|
count="$(tr ';' '\n' <<< "$children" | grep -c '\S')" \
|
||||||
|
|| count=0
|
||||||
|
local idx=0
|
||||||
|
# Splitting is intentional here
|
||||||
|
# shellcheck disable=SC2086
|
||||||
|
for id in ${children//';'/ }; do
|
||||||
|
idx="$((idx + 1))"
|
||||||
|
[[ $idx == "$count" ]] \
|
||||||
|
&& summary_depth_continues[$depth]=false
|
||||||
|
print_summary_tree "$id"
|
||||||
|
# separate blocks by newline
|
||||||
|
[[ ${summary_depth_continues[0]} == "true" ]] && [[ $depth == 1 ]] && [[ $idx == "$count" ]] \
|
||||||
|
&& elog
|
||||||
|
done
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
function apply_disk_actions() {
|
||||||
|
local param
|
||||||
|
local current_params=()
|
||||||
|
for param in "${DISK_ACTIONS[@]}"; do
|
||||||
|
if [[ $param == ';' ]]; then
|
||||||
|
apply_disk_action "${current_params[@]}"
|
||||||
|
current_params=()
|
||||||
|
else
|
||||||
|
current_params+=("$param")
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
}
|
||||||
|
|
||||||
|
function summarize_disk_actions() {
|
||||||
|
elog "[1mCurrent lsblk output:[m"
|
||||||
|
for_line_in <(lsblk \
|
||||||
|
|| die "Error in lsblk") elog
|
||||||
|
|
||||||
|
local disk_action_summarize_only=true
|
||||||
|
declare -A summary_tree
|
||||||
|
declare -A summary_name
|
||||||
|
declare -A summary_hint
|
||||||
|
declare -A summary_ptr
|
||||||
|
declare -A summary_desc
|
||||||
|
declare -A summary_depth_continues
|
||||||
|
apply_disk_actions
|
||||||
|
|
||||||
|
local depth=-1
|
||||||
|
elog
|
||||||
|
elog "[1mConfigured disk layout:[m"
|
||||||
|
elog ────────────────────────────────────────────────────────────────────────────────
|
||||||
|
elog "$(printf '%-26s %-28s %s' NODE ID OPTIONS)"
|
||||||
|
elog ────────────────────────────────────────────────────────────────────────────────
|
||||||
|
print_summary_tree __root__
|
||||||
|
elog ────────────────────────────────────────────────────────────────────────────────
|
||||||
|
}
|
||||||
|
|
||||||
|
function apply_disk_configuration() {
|
||||||
|
summarize_disk_actions
|
||||||
|
|
||||||
|
if [[ $NO_PARTITIONING_OR_FORMATTING == true ]]; then
|
||||||
|
elog "You have chosen an existing disk configuration. No devices will"
|
||||||
|
elog "actually be re-partitioned or formatted. Please make sure that all"
|
||||||
|
elog "devices are already formatted."
|
||||||
|
else
|
||||||
|
ewarn "Please ensure that all selected devices are fully unmounted and are"
|
||||||
|
ewarn "not otherwise in use by the system. This includes stopping mdadm arrays"
|
||||||
|
ewarn "and closing opened luks volumes if applicable for all relevant devices."
|
||||||
|
ewarn "Otherwise, automatic partitioning may fail."
|
||||||
|
fi
|
||||||
|
ask "Do you really want to apply this disk configuration?" \
|
||||||
|
|| die "Aborted"
|
||||||
|
countdown "Applying in " 5
|
||||||
|
|
||||||
|
maybe_exec 'before_disk_configuration'
|
||||||
|
|
||||||
|
einfo "Applying disk configuration"
|
||||||
|
apply_disk_actions
|
||||||
|
|
||||||
|
einfo "Disk configuration was applied successfully"
|
||||||
|
elog "[1mNew lsblk output:[m"
|
||||||
|
for_line_in <(lsblk \
|
||||||
|
|| die "Error in lsblk") elog
|
||||||
|
|
||||||
|
maybe_exec 'after_disk_configuration'
|
||||||
|
}
|
||||||
|
|
||||||
|
function mount_efivars() {
|
||||||
|
# Skip if already mounted
|
||||||
|
mountpoint -q -- "/sys/firmware/efi/efivars" \
|
||||||
|
&& return
|
||||||
|
|
||||||
|
# Mount efivars
|
||||||
|
einfo "Mounting efivars"
|
||||||
|
mount -t efivarfs efivarfs "/sys/firmware/efi/efivars" \
|
||||||
|
|| die "Could not mount efivarfs"
|
||||||
|
}
|
||||||
|
|
||||||
|
function mount_by_id() {
|
||||||
|
local dev
|
||||||
|
local id="$1"
|
||||||
|
local mountpoint="$2"
|
||||||
|
|
||||||
|
# Skip if already mounted
|
||||||
|
mountpoint -q -- "$mountpoint" \
|
||||||
|
&& return
|
||||||
|
|
||||||
|
# Mount device
|
||||||
|
einfo "Mounting device with id=$id to '$mountpoint'"
|
||||||
|
mkdir -p "$mountpoint" \
|
||||||
|
|| die "Could not create mountpoint directory '$mountpoint'"
|
||||||
|
dev="$(resolve_device_by_id "$id")" \
|
||||||
|
|| die "Could not resolve device with id=$id"
|
||||||
|
mount "$dev" "$mountpoint" \
|
||||||
|
|| die "Could not mount device '$dev'"
|
||||||
|
}
|
||||||
|
|
||||||
|
function mount_root() {
|
||||||
|
if [[ $USED_ZFS == "true" ]] && ! mountpoint -q -- "$ROOT_MOUNTPOINT"; then
|
||||||
|
die "Error: Expected zfs to be mounted under '$ROOT_MOUNTPOINT', but it isn't."
|
||||||
|
else
|
||||||
|
mount_by_id "$DISK_ID_ROOT" "$ROOT_MOUNTPOINT"
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
function bind_repo_dir() {
|
||||||
|
# Use new location by default
|
||||||
|
export GENTOO_INSTALL_REPO_DIR="$GENTOO_INSTALL_REPO_BIND"
|
||||||
|
|
||||||
|
# Bind the repo dir to a location in /tmp,
|
||||||
|
# so it can be accessed from within the chroot
|
||||||
|
mountpoint -q -- "$GENTOO_INSTALL_REPO_BIND" \
|
||||||
|
&& return
|
||||||
|
|
||||||
|
# Mount root device
|
||||||
|
einfo "Bind mounting repo directory"
|
||||||
|
mkdir -p "$GENTOO_INSTALL_REPO_BIND" \
|
||||||
|
|| die "Could not create mountpoint directory '$GENTOO_INSTALL_REPO_BIND'"
|
||||||
|
mount --bind "$GENTOO_INSTALL_REPO_DIR_ORIGINAL" "$GENTOO_INSTALL_REPO_BIND" \
|
||||||
|
|| die "Could not bind mount '$GENTOO_INSTALL_REPO_DIR_ORIGINAL' to '$GENTOO_INSTALL_REPO_BIND'"
|
||||||
|
}
|
||||||
|
|
||||||
|
function download_stage3() {
|
||||||
|
cd "$TMP_DIR" \
|
||||||
|
|| die "Could not cd into '$TMP_DIR'"
|
||||||
|
|
||||||
|
local STAGE3_RELEASES="$GENTOO_MIRROR/releases/$GENTOO_ARCH/autobuilds/current-$STAGE3_BASENAME/"
|
||||||
|
|
||||||
|
# Download upstream list of files
|
||||||
|
CURRENT_STAGE3="$(download_stdout "$STAGE3_RELEASES")" \
|
||||||
|
|| die "Could not retrieve list of tarballs"
|
||||||
|
# Decode urlencoded strings
|
||||||
|
CURRENT_STAGE3=$(python3 -c 'import sys, urllib.parse; print(urllib.parse.unquote(sys.stdin.read()))' <<< "$CURRENT_STAGE3")
|
||||||
|
# Parse output for correct filename
|
||||||
|
CURRENT_STAGE3="$(grep -o "\"${STAGE3_BASENAME}-[0-9A-Z]*.tar.xz\"" <<< "$CURRENT_STAGE3" \
|
||||||
|
| sort -u | head -1)" \
|
||||||
|
|| die "Could not parse list of tarballs"
|
||||||
|
# Strip quotes
|
||||||
|
CURRENT_STAGE3="${CURRENT_STAGE3:1:-1}"
|
||||||
|
# File to indiciate successful verification
|
||||||
|
CURRENT_STAGE3_VERIFIED="${CURRENT_STAGE3}.verified"
|
||||||
|
|
||||||
|
maybe_exec 'before_download_stage3' "$STAGE3_BASENAME"
|
||||||
|
|
||||||
|
# Download file if not already downloaded
|
||||||
|
if [[ -e $CURRENT_STAGE3_VERIFIED ]]; then
|
||||||
|
einfo "$STAGE3_BASENAME tarball already downloaded and verified"
|
||||||
|
else
|
||||||
|
einfo "Downloading $STAGE3_BASENAME tarball"
|
||||||
|
download "$STAGE3_RELEASES/${CURRENT_STAGE3}" "${CURRENT_STAGE3}"
|
||||||
|
download "$STAGE3_RELEASES/${CURRENT_STAGE3}.DIGESTS" "${CURRENT_STAGE3}.DIGESTS"
|
||||||
|
|
||||||
|
# Import gentoo keys
|
||||||
|
einfo "Importing gentoo gpg key"
|
||||||
|
local GENTOO_GPG_KEY="$TMP_DIR/gentoo-keys.gpg"
|
||||||
|
download "https://gentoo.org/.well-known/openpgpkey/hu/wtktzo4gyuhzu8a4z5fdj3fgmr1u6tob?l=releng" "$GENTOO_GPG_KEY" \
|
||||||
|
|| die "Could not retrieve gentoo gpg key"
|
||||||
|
gpg --quiet --import < "$GENTOO_GPG_KEY" \
|
||||||
|
|| die "Could not import gentoo gpg key"
|
||||||
|
|
||||||
|
# Verify DIGESTS signature
|
||||||
|
einfo "Verifying tarball signature"
|
||||||
|
gpg --quiet --verify "${CURRENT_STAGE3}.DIGESTS" \
|
||||||
|
|| die "Signature of '${CURRENT_STAGE3}.DIGESTS' invalid!"
|
||||||
|
|
||||||
|
# Check hashes
|
||||||
|
einfo "Verifying tarball integrity"
|
||||||
|
# Replace any absolute paths in the digest file with just the stage3 basename, so it will be found by rhash
|
||||||
|
digest_line=$(grep 'tar.xz$' "${CURRENT_STAGE3}.DIGESTS" | sed -e 's/ .*stage3-/ stage3-/')
|
||||||
|
if type rhash &>/dev/null; then
|
||||||
|
rhash -P --check <(echo "# SHA512"; echo "$digest_line") \
|
||||||
|
|| die "Checksum mismatch!"
|
||||||
|
else
|
||||||
|
sha512sum --check <<< "$digest_line" \
|
||||||
|
|| die "Checksum mismatch!"
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Create verification file in case the script is restarted
|
||||||
|
touch_or_die 0644 "$CURRENT_STAGE3_VERIFIED"
|
||||||
|
fi
|
||||||
|
|
||||||
|
maybe_exec 'after_download_stage3' "${CURRENT_STAGE3}"
|
||||||
|
}
|
||||||
|
|
||||||
|
function extract_stage3() {
|
||||||
|
mount_root
|
||||||
|
|
||||||
|
[[ -n $CURRENT_STAGE3 ]] \
|
||||||
|
|| die "CURRENT_STAGE3 is not set"
|
||||||
|
[[ -e "$TMP_DIR/$CURRENT_STAGE3" ]] \
|
||||||
|
|| die "stage3 file does not exist"
|
||||||
|
|
||||||
|
maybe_exec 'before_extract_stage3' "$TMP_DIR/$CURRENT_STAGE3" "$ROOT_MOUNTPOINT"
|
||||||
|
|
||||||
|
# Go to root directory
|
||||||
|
cd "$ROOT_MOUNTPOINT" \
|
||||||
|
|| die "Could not move to '$ROOT_MOUNTPOINT'"
|
||||||
|
# Ensure the directory is empty
|
||||||
|
find . -mindepth 1 -maxdepth 1 -not -name 'lost+found' \
|
||||||
|
| grep -q . \
|
||||||
|
&& die "root directory '$ROOT_MOUNTPOINT' is not empty"
|
||||||
|
|
||||||
|
# Extract tarball
|
||||||
|
einfo "Extracting stage3 tarball"
|
||||||
|
tar xpf "$TMP_DIR/$CURRENT_STAGE3" --xattrs --numeric-owner \
|
||||||
|
|| die "Error while extracting tarball"
|
||||||
|
cd "$TMP_DIR" \
|
||||||
|
|| die "Could not cd into '$TMP_DIR'"
|
||||||
|
|
||||||
|
maybe_exec 'after_extract_stage3' "$TMP_DIR/$CURRENT_STAGE3" "$ROOT_MOUNTPOINT"
|
||||||
|
}
|
||||||
|
|
||||||
|
function gentoo_umount() {
|
||||||
|
if mountpoint -q -- "$ROOT_MOUNTPOINT"; then
|
||||||
|
einfo "Unmounting root filesystem"
|
||||||
|
umount -R -l "$ROOT_MOUNTPOINT" \
|
||||||
|
|| die "Could not unmount filesystems"
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
function init_bash() {
|
||||||
|
source /etc/profile
|
||||||
|
umask 0077
|
||||||
|
export PS1='(chroot) \[[0;31m\]\u\[[1;31m\]@\h \[[1;34m\]\w \[[m\]\$ \[[m\]'
|
||||||
|
}; export -f init_bash
|
||||||
|
|
||||||
|
function env_update() {
|
||||||
|
env-update \
|
||||||
|
|| die "Error in env-update"
|
||||||
|
source /etc/profile \
|
||||||
|
|| die "Could not source /etc/profile"
|
||||||
|
umask 0077
|
||||||
|
}
|
||||||
|
|
||||||
|
function mkdir_or_die() {
|
||||||
|
# shellcheck disable=SC2174
|
||||||
|
mkdir -m "$1" -p "$2" \
|
||||||
|
|| die "Could not create directory '$2'"
|
||||||
|
}
|
||||||
|
|
||||||
|
function touch_or_die() {
|
||||||
|
touch "$2" \
|
||||||
|
|| die "Could not touch '$2'"
|
||||||
|
chmod "$1" "$2"
|
||||||
|
}
|
||||||
|
|
||||||
|
# $1: root directory
|
||||||
|
# $@: command...
|
||||||
|
function gentoo_chroot() {
|
||||||
|
if [[ $# -eq 1 ]]; then
|
||||||
|
einfo "To later unmount all virtual filesystems, simply use umount -l ${1@Q}"
|
||||||
|
gentoo_chroot "$1" /bin/bash --init-file <(echo 'init_bash')
|
||||||
|
fi
|
||||||
|
|
||||||
|
[[ ${EXECUTED_IN_CHROOT-false} == "false" ]] \
|
||||||
|
|| die "Already in chroot"
|
||||||
|
|
||||||
|
local chroot_dir="$1"
|
||||||
|
shift
|
||||||
|
|
||||||
|
# Bind repo directory to tmp
|
||||||
|
bind_repo_dir
|
||||||
|
|
||||||
|
# Copy resolv.conf
|
||||||
|
einfo "Preparing chroot environment"
|
||||||
|
install --mode=0644 /etc/resolv.conf "$chroot_dir/etc/resolv.conf" \
|
||||||
|
|| die "Could not copy resolv.conf"
|
||||||
|
|
||||||
|
# Mount virtual filesystems
|
||||||
|
einfo "Mounting virtual filesystems"
|
||||||
|
(
|
||||||
|
mountpoint -q -- "$chroot_dir/proc" || mount -t proc /proc "$chroot_dir/proc" || exit 1
|
||||||
|
mountpoint -q -- "$chroot_dir/run" || {
|
||||||
|
mount --rbind /run "$chroot_dir/run" &&
|
||||||
|
mount --make-rslave "$chroot_dir/run"; } || exit 1
|
||||||
|
mountpoint -q -- "$chroot_dir/tmp" || {
|
||||||
|
mount --rbind /tmp "$chroot_dir/tmp" &&
|
||||||
|
mount --make-rslave "$chroot_dir/tmp"; } || exit 1
|
||||||
|
mountpoint -q -- "$chroot_dir/sys" || {
|
||||||
|
mount --rbind /sys "$chroot_dir/sys" &&
|
||||||
|
mount --make-rslave "$chroot_dir/sys"; } || exit 1
|
||||||
|
mountpoint -q -- "$chroot_dir/dev" || {
|
||||||
|
mount --rbind /dev "$chroot_dir/dev" &&
|
||||||
|
mount --make-rslave "$chroot_dir/dev"; } || exit 1
|
||||||
|
) || die "Could not mount virtual filesystems"
|
||||||
|
|
||||||
|
# Cache lsblk output, because it doesn't work correctly in chroot (returns almost no info for devices, e.g. empty uuids)
|
||||||
|
cache_lsblk_output
|
||||||
|
|
||||||
|
# Execute command
|
||||||
|
einfo "Chrooting..."
|
||||||
|
EXECUTED_IN_CHROOT=true \
|
||||||
|
TMP_DIR="$TMP_DIR" \
|
||||||
|
CACHED_LSBLK_OUTPUT="$CACHED_LSBLK_OUTPUT" \
|
||||||
|
exec chroot -- "$chroot_dir" "$GENTOO_INSTALL_REPO_DIR/scripts/dispatch_chroot.sh" "$@" \
|
||||||
|
|| die "Failed to chroot into '$chroot_dir'."
|
||||||
|
}
|
||||||
|
|
||||||
|
function enable_service() {
|
||||||
|
if [[ $SYSTEMD == "true" ]]; then
|
||||||
|
try systemctl enable "$1"
|
||||||
|
else
|
||||||
|
try rc-update add "$1" default
|
||||||
|
fi
|
||||||
|
}
|
555
scripts/main.sh
Normal file
555
scripts/main.sh
Normal file
|
@ -0,0 +1,555 @@
|
||||||
|
# shellcheck source=./scripts/protection.sh
|
||||||
|
source "$GENTOO_INSTALL_REPO_DIR/scripts/protection.sh" || exit 1
|
||||||
|
|
||||||
|
|
||||||
|
################################################
|
||||||
|
# Functions
|
||||||
|
|
||||||
|
function install_stage3() {
|
||||||
|
prepare_installation_environment
|
||||||
|
apply_disk_configuration
|
||||||
|
download_stage3
|
||||||
|
extract_stage3
|
||||||
|
}
|
||||||
|
|
||||||
|
function configure_base_system() {
|
||||||
|
if [[ $MUSL == "true" ]]; then
|
||||||
|
einfo "Installing musl-locales"
|
||||||
|
if [[ $USE_PORTAGE_TESTING == "false" ]]; then
|
||||||
|
echo "sys-apps/musl-locales" >> /etc/portage/package.accept_keywords/musl-locales
|
||||||
|
fi
|
||||||
|
try emerge --verbose sys-apps/musl-locales
|
||||||
|
else
|
||||||
|
einfo "Generating locales"
|
||||||
|
echo "$LOCALES" > /etc/locale.gen \
|
||||||
|
|| die "Could not write /etc/locale.gen"
|
||||||
|
locale-gen \
|
||||||
|
|| die "Could not generate locales"
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [[ $SYSTEMD == "true" ]]; then
|
||||||
|
einfo "Setting machine-id"
|
||||||
|
systemd-machine-id-setup \
|
||||||
|
|| die "Could not setup systemd machine id"
|
||||||
|
|
||||||
|
# Set hostname
|
||||||
|
einfo "Selecting hostname"
|
||||||
|
echo "$HOSTNAME" > /etc/hostname \
|
||||||
|
|| die "Could not write /etc/hostname"
|
||||||
|
|
||||||
|
# Set keymap
|
||||||
|
einfo "Selecting keymap"
|
||||||
|
echo "KEYMAP=$KEYMAP" > /etc/vconsole.conf \
|
||||||
|
|| die "Could not write /etc/vconsole.conf"
|
||||||
|
|
||||||
|
# Set locale
|
||||||
|
einfo "Selecting locale"
|
||||||
|
echo "LANG=$LOCALE" > /etc/locale.conf \
|
||||||
|
|| die "Could not write /etc/locale.conf"
|
||||||
|
|
||||||
|
einfo "Selecting timezone"
|
||||||
|
ln -sfn "../usr/share/zoneinfo/$TIMEZONE" /etc/localtime \
|
||||||
|
|| die "Could not change /etc/localtime link"
|
||||||
|
else
|
||||||
|
# Set hostname
|
||||||
|
einfo "Selecting hostname"
|
||||||
|
sed -i "/hostname=/c\\hostname=\"$HOSTNAME\"" /etc/conf.d/hostname \
|
||||||
|
|| die "Could not sed replace in /etc/conf.d/hostname"
|
||||||
|
|
||||||
|
# Set timezone
|
||||||
|
if [[ $MUSL == "true" ]]; then
|
||||||
|
try emerge -v sys-libs/timezone-data
|
||||||
|
einfo "Selecting timezone"
|
||||||
|
echo -e "\nTZ=\"$TIMEZONE\"" >> /etc/env.d/00musl \
|
||||||
|
|| die "Could not write to /etc/env.d/00musl"
|
||||||
|
else
|
||||||
|
einfo "Selecting timezone"
|
||||||
|
echo "$TIMEZONE" > /etc/timezone \
|
||||||
|
|| die "Could not write /etc/timezone"
|
||||||
|
chmod 644 /etc/timezone \
|
||||||
|
|| die "Could not set correct permissions for /etc/timezone"
|
||||||
|
try emerge -v --config sys-libs/timezone-data
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Set keymap
|
||||||
|
einfo "Selecting keymap"
|
||||||
|
sed -i "/keymap=/c\\keymap=\"$KEYMAP\"" /etc/conf.d/keymaps \
|
||||||
|
|| die "Could not sed replace in /etc/conf.d/keymaps"
|
||||||
|
|
||||||
|
# Set locale
|
||||||
|
einfo "Selecting locale"
|
||||||
|
try eselect locale set "$LOCALE"
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Update environment
|
||||||
|
env_update
|
||||||
|
}
|
||||||
|
|
||||||
|
function configure_portage() {
|
||||||
|
# Prepare /etc/portage for autounmask
|
||||||
|
mkdir_or_die 0755 "/etc/portage/package.use"
|
||||||
|
touch_or_die 0644 "/etc/portage/package.use/zz-autounmask"
|
||||||
|
mkdir_or_die 0755 "/etc/portage/package.keywords"
|
||||||
|
touch_or_die 0644 "/etc/portage/package.keywords/zz-autounmask"
|
||||||
|
touch_or_die 0644 "/etc/portage/package.license"
|
||||||
|
|
||||||
|
if [[ $SELECT_MIRRORS == "true" ]]; then
|
||||||
|
einfo "Temporarily installing mirrorselect"
|
||||||
|
try emerge --verbose --oneshot app-portage/mirrorselect
|
||||||
|
|
||||||
|
einfo "Selecting fastest portage mirrors"
|
||||||
|
mirrorselect_params=("-s" "4" "-b" "10")
|
||||||
|
[[ $SELECT_MIRRORS_LARGE_FILE == "true" ]] \
|
||||||
|
&& mirrorselect_params+=("-D")
|
||||||
|
try mirrorselect "${mirrorselect_params[@]}"
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [[ $ENABLE_BINPKG == "true" ]]; then
|
||||||
|
echo 'FEATURES="getbinpkg"' >> /etc/portage/make.conf
|
||||||
|
getuto
|
||||||
|
chmod 644 /etc/portage/gnupg/pubring.kbx
|
||||||
|
fi
|
||||||
|
|
||||||
|
chmod 644 /etc/portage/make.conf \
|
||||||
|
|| die "Could not chmod 644 /etc/portage/make.conf"
|
||||||
|
}
|
||||||
|
|
||||||
|
function enable_sshd() {
|
||||||
|
einfo "Installing and enabling sshd"
|
||||||
|
install -m0600 -o root -g root "$GENTOO_INSTALL_REPO_DIR/contrib/sshd_config" /etc/ssh/sshd_config \
|
||||||
|
|| die "Could not install /etc/ssh/sshd_config"
|
||||||
|
enable_service sshd
|
||||||
|
}
|
||||||
|
|
||||||
|
function install_authorized_keys() {
|
||||||
|
mkdir_or_die 0700 "/root/"
|
||||||
|
mkdir_or_die 0700 "/root/.ssh"
|
||||||
|
|
||||||
|
if [[ -n "$ROOT_SSH_AUTHORIZED_KEYS" ]]; then
|
||||||
|
einfo "Adding authorized keys for root"
|
||||||
|
touch_or_die 0600 "/root/.ssh/authorized_keys"
|
||||||
|
echo "$ROOT_SSH_AUTHORIZED_KEYS" > "/root/.ssh/authorized_keys" \
|
||||||
|
|| die "Could not add ssh key to /root/.ssh/authorized_keys"
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
function generate_initramfs() {
|
||||||
|
local output="$1"
|
||||||
|
|
||||||
|
# Generate initramfs
|
||||||
|
einfo "Generating initramfs"
|
||||||
|
|
||||||
|
local modules=()
|
||||||
|
[[ $USED_RAID == "true" ]] \
|
||||||
|
&& modules+=("mdraid")
|
||||||
|
[[ $USED_LUKS == "true" ]] \
|
||||||
|
&& modules+=("crypt crypt-gpg")
|
||||||
|
[[ $USED_BTRFS == "true" ]] \
|
||||||
|
&& modules+=("btrfs")
|
||||||
|
[[ $USED_ZFS == "true" ]] \
|
||||||
|
&& modules+=("zfs")
|
||||||
|
|
||||||
|
local kver
|
||||||
|
kver="$(readlink /usr/src/linux)" \
|
||||||
|
|| die "Could not figure out kernel version from /usr/src/linux symlink."
|
||||||
|
kver="${kver#linux-}"
|
||||||
|
|
||||||
|
dracut_opts=()
|
||||||
|
if [[ $SYSTEMD == "true" && $SYSTEMD_INITRAMFS_SSHD == "true" ]]; then
|
||||||
|
cd /tmp || die "Could not change into /tmp"
|
||||||
|
try git clone https://github.com/gsauthof/dracut-sshd
|
||||||
|
try cp -r dracut-sshd/46sshd /usr/lib/dracut/modules.d
|
||||||
|
sed -e 's/^Type=notify/Type=simple/' \
|
||||||
|
-e 's@^\(ExecStart=/usr/sbin/sshd\) -D@\1 -e -D@' \
|
||||||
|
-i /usr/lib/dracut/modules.d/46sshd/sshd.service \
|
||||||
|
|| die "Could not replace sshd options in service file"
|
||||||
|
dracut_opts+=("--install" "/etc/systemd/network/20-wired.network")
|
||||||
|
modules+=("systemd-networkd")
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Generate initramfs
|
||||||
|
# TODO --conf "/dev/null" \
|
||||||
|
# TODO --confdir "/dev/null" \
|
||||||
|
try dracut \
|
||||||
|
--kver "$kver" \
|
||||||
|
--zstd \
|
||||||
|
--no-hostonly \
|
||||||
|
--ro-mnt \
|
||||||
|
--add "bash ${modules[*]}" \
|
||||||
|
"${dracut_opts[@]}" \
|
||||||
|
--force \
|
||||||
|
"$output"
|
||||||
|
|
||||||
|
# Create script to repeat initramfs generation
|
||||||
|
cat > "$(dirname "$output")/generate_initramfs.sh" <<EOF
|
||||||
|
#!/bin/bash
|
||||||
|
kver="\$1"
|
||||||
|
output="\$2" # At setup time, this was "$output"
|
||||||
|
[[ -n "\$kver" ]] || { echo "usage \$0 <kernel_version> <output>" >&2; exit 1; }
|
||||||
|
dracut \\
|
||||||
|
--kver "\$kver" \\
|
||||||
|
--zstd \\
|
||||||
|
--no-hostonly \\
|
||||||
|
--ro-mnt \\
|
||||||
|
--add "bash ${modules[*]}" \\
|
||||||
|
${dracut_opts[@]@Q} \\
|
||||||
|
--force \\
|
||||||
|
"\$output"
|
||||||
|
EOF
|
||||||
|
}
|
||||||
|
|
||||||
|
function get_cmdline() {
|
||||||
|
local cmdline=("rd.vconsole.keymap=$KEYMAP_INITRAMFS")
|
||||||
|
cmdline+=("${DISK_DRACUT_CMDLINE[@]}")
|
||||||
|
|
||||||
|
if [[ $USED_ZFS != "true" ]]; then
|
||||||
|
cmdline+=("root=UUID=$(get_blkid_uuid_for_id "$DISK_ID_ROOT")")
|
||||||
|
fi
|
||||||
|
|
||||||
|
echo -n "${cmdline[*]}"
|
||||||
|
}
|
||||||
|
|
||||||
|
function install_kernel_efi() {
|
||||||
|
try emerge --verbose sys-boot/efibootmgr
|
||||||
|
|
||||||
|
# Copy kernel to EFI
|
||||||
|
local kernel_file
|
||||||
|
kernel_file="$(find "/boot" \( -name "vmlinuz-*" -or -name 'kernel-*' \) -printf '%f\n' | sort -V | tail -n 1)" \
|
||||||
|
|| die "Could not list newest kernel file"
|
||||||
|
|
||||||
|
try cp "/boot/$kernel_file" "/boot/efi/vmlinuz.efi"
|
||||||
|
|
||||||
|
# Generate initramfs
|
||||||
|
generate_initramfs "/boot/efi/initramfs.img"
|
||||||
|
|
||||||
|
# Create boot entry
|
||||||
|
einfo "Creating efi boot entry"
|
||||||
|
local efipartdev
|
||||||
|
efipartdev="$(resolve_device_by_id "$DISK_ID_EFI")" \
|
||||||
|
|| die "Could not resolve device with id=$DISK_ID_EFI"
|
||||||
|
efipartdev="$(realpath "$efipartdev")" \
|
||||||
|
|| die "Error in realpath '$efipartdev'"
|
||||||
|
local sys_efipart
|
||||||
|
sys_efipart="/sys/class/block/$(basename "$efipartdev")" \
|
||||||
|
|| die "Could not construct /sys path to efi partition"
|
||||||
|
local efipartnum
|
||||||
|
efipartnum="$(cat "$sys_efipart/partition")" \
|
||||||
|
|| die "Failed to find partition number for EFI partition $efipartdev"
|
||||||
|
local gptdev
|
||||||
|
gptdev="/dev/$(basename "$(readlink -f "$sys_efipart/..")")" \
|
||||||
|
|| die "Failed to find parent device for EFI partition $efipartdev"
|
||||||
|
if [[ ! -e "$gptdev" ]] || [[ -z "$gptdev" ]]; then
|
||||||
|
gptdev="$(resolve_device_by_id "${DISK_ID_PART_TO_GPT_ID[$DISK_ID_EFI]}")" \
|
||||||
|
|| die "Could not resolve device with id=${DISK_ID_PART_TO_GPT_ID[$DISK_ID_EFI]}"
|
||||||
|
fi
|
||||||
|
try efibootmgr --verbose --create --disk "$gptdev" --part "$efipartnum" --label "gentoo" --loader '\vmlinuz.efi' --unicode 'initrd=\initramfs.img'" $(get_cmdline)"
|
||||||
|
|
||||||
|
# Create script to repeat adding efibootmgr entry
|
||||||
|
cat > "/boot/efi/efibootmgr_add_entry.sh" <<EOF
|
||||||
|
#!/bin/bash
|
||||||
|
# This is the command that was used to create the efibootmgr entry when the
|
||||||
|
# system was installed using gentoo-install.
|
||||||
|
efibootmgr --verbose --create --disk "$gptdev" --part "$efipartnum" --label "gentoo" --loader '\\vmlinuz.efi' --unicode 'initrd=\\initramfs.img'" $(get_cmdline)"
|
||||||
|
EOF
|
||||||
|
}
|
||||||
|
|
||||||
|
function generate_syslinux_cfg() {
|
||||||
|
cat <<EOF
|
||||||
|
DEFAULT gentoo
|
||||||
|
PROMPT 0
|
||||||
|
TIMEOUT 0
|
||||||
|
|
||||||
|
LABEL gentoo
|
||||||
|
LINUX ../vmlinuz-current
|
||||||
|
APPEND initrd=../initramfs.img $(get_cmdline)
|
||||||
|
EOF
|
||||||
|
}
|
||||||
|
|
||||||
|
function install_kernel_bios() {
|
||||||
|
try emerge --verbose sys-boot/syslinux
|
||||||
|
|
||||||
|
# Link kernel to known name
|
||||||
|
local kernel_file
|
||||||
|
kernel_file="$(find "/boot" \( -name "vmlinuz-*" -or -name 'kernel-*' \) -printf '%f\n' | sort -V | tail -n 1)" \
|
||||||
|
|| die "Could not list newest kernel file"
|
||||||
|
|
||||||
|
try cp "/boot/$kernel_file" "/boot/bios/vmlinuz-current"
|
||||||
|
|
||||||
|
# Generate initramfs
|
||||||
|
generate_initramfs "/boot/bios/initramfs.img"
|
||||||
|
|
||||||
|
# Install syslinux
|
||||||
|
einfo "Installing syslinux"
|
||||||
|
local biosdev
|
||||||
|
biosdev="$(resolve_device_by_id "$DISK_ID_BIOS")" \
|
||||||
|
|| die "Could not resolve device with id=$DISK_ID_BIOS"
|
||||||
|
mkdir_or_die 0700 "/boot/bios/syslinux"
|
||||||
|
try syslinux --directory syslinux --install "$biosdev"
|
||||||
|
|
||||||
|
# Create syslinux.cfg
|
||||||
|
generate_syslinux_cfg > /boot/bios/syslinux/syslinux.cfg \
|
||||||
|
|| die "Could save generated syslinux.cfg"
|
||||||
|
|
||||||
|
# Install syslinux MBR record
|
||||||
|
einfo "Copying syslinux MBR record"
|
||||||
|
local gptdev
|
||||||
|
gptdev="$(resolve_device_by_id "${DISK_ID_PART_TO_GPT_ID[$DISK_ID_BIOS]}")" \
|
||||||
|
|| die "Could not resolve device with id=${DISK_ID_PART_TO_GPT_ID[$DISK_ID_BIOS]}"
|
||||||
|
try dd bs=440 conv=notrunc count=1 if=/usr/share/syslinux/gptmbr.bin of="$gptdev"
|
||||||
|
}
|
||||||
|
|
||||||
|
function install_kernel() {
|
||||||
|
# Install vanilla kernel
|
||||||
|
einfo "Installing vanilla kernel and related tools"
|
||||||
|
|
||||||
|
if [[ $IS_EFI == "true" ]]; then
|
||||||
|
install_kernel_efi
|
||||||
|
else
|
||||||
|
install_kernel_bios
|
||||||
|
fi
|
||||||
|
|
||||||
|
einfo "Installing linux-firmware"
|
||||||
|
echo "sys-kernel/linux-firmware linux-fw-redistributable no-source-code" >> /etc/portage/package.license \
|
||||||
|
|| die "Could not write to /etc/portage/package.license"
|
||||||
|
try emerge --verbose linux-firmware
|
||||||
|
}
|
||||||
|
|
||||||
|
function add_fstab_entry() {
|
||||||
|
printf '%-46s %-24s %-6s %-96s %s\n' "$1" "$2" "$3" "$4" "$5" >> /etc/fstab \
|
||||||
|
|| die "Could not append entry to fstab"
|
||||||
|
}
|
||||||
|
|
||||||
|
function generate_fstab() {
|
||||||
|
einfo "Generating fstab"
|
||||||
|
install -m0644 -o root -g root "$GENTOO_INSTALL_REPO_DIR/contrib/fstab" /etc/fstab \
|
||||||
|
|| die "Could not overwrite /etc/fstab"
|
||||||
|
if [[ $USED_ZFS != "true" && -n $DISK_ID_ROOT_TYPE ]]; then
|
||||||
|
add_fstab_entry "UUID=$(get_blkid_uuid_for_id "$DISK_ID_ROOT")" "/" "$DISK_ID_ROOT_TYPE" "$DISK_ID_ROOT_MOUNT_OPTS" "0 1"
|
||||||
|
fi
|
||||||
|
if [[ $IS_EFI == "true" ]]; then
|
||||||
|
add_fstab_entry "UUID=$(get_blkid_uuid_for_id "$DISK_ID_EFI")" "/boot/efi" "vfat" "defaults,noatime,fmask=0177,dmask=0077,noexec,nodev,nosuid,discard" "0 2"
|
||||||
|
else
|
||||||
|
add_fstab_entry "UUID=$(get_blkid_uuid_for_id "$DISK_ID_BIOS")" "/boot/bios" "vfat" "defaults,noatime,fmask=0177,dmask=0077,noexec,nodev,nosuid,discard" "0 2"
|
||||||
|
fi
|
||||||
|
if [[ -v "DISK_ID_SWAP" ]]; then
|
||||||
|
add_fstab_entry "UUID=$(get_blkid_uuid_for_id "$DISK_ID_SWAP")" "none" "swap" "defaults,discard" "0 0"
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
function main_install_gentoo_in_chroot() {
|
||||||
|
[[ $# == 0 ]] || die "Too many arguments"
|
||||||
|
|
||||||
|
maybe_exec 'before_install'
|
||||||
|
|
||||||
|
# Remove the root password, making the account accessible for automated
|
||||||
|
# tasks during the period of installation.
|
||||||
|
einfo "Clearing root password"
|
||||||
|
passwd -d root \
|
||||||
|
|| die "Could not change root password"
|
||||||
|
|
||||||
|
if [[ $IS_EFI == "true" ]]; then
|
||||||
|
# Mount efi partition
|
||||||
|
mount_efivars
|
||||||
|
einfo "Mounting efi partition"
|
||||||
|
mount_by_id "$DISK_ID_EFI" "/boot/efi"
|
||||||
|
else
|
||||||
|
# Mount bios partition
|
||||||
|
einfo "Mounting bios partition"
|
||||||
|
mount_by_id "$DISK_ID_BIOS" "/boot/bios"
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Sync portage
|
||||||
|
einfo "Syncing portage tree"
|
||||||
|
try emerge-webrsync
|
||||||
|
|
||||||
|
# Configure basic system things like timezone, locale, ...
|
||||||
|
maybe_exec 'before_configure_base_system'
|
||||||
|
configure_base_system
|
||||||
|
maybe_exec 'after_configure_base_system'
|
||||||
|
|
||||||
|
# Prepare portage environment
|
||||||
|
maybe_exec 'before_configure_portage'
|
||||||
|
configure_portage
|
||||||
|
|
||||||
|
# Install git (for git portage overlays)
|
||||||
|
einfo "Installing git"
|
||||||
|
try emerge --verbose dev-vcs/git
|
||||||
|
|
||||||
|
if [[ "$PORTAGE_SYNC_TYPE" == "git" ]]; then
|
||||||
|
mkdir_or_die 0755 "/etc/portage/repos.conf"
|
||||||
|
cat > /etc/portage/repos.conf/gentoo.conf <<EOF
|
||||||
|
[DEFAULT]
|
||||||
|
main-repo = gentoo
|
||||||
|
|
||||||
|
[gentoo]
|
||||||
|
location = /var/db/repos/gentoo
|
||||||
|
sync-type = git
|
||||||
|
sync-uri = $PORTAGE_GIT_MIRROR
|
||||||
|
auto-sync = yes
|
||||||
|
sync-depth = $([[ $PORTAGE_GIT_FULL_HISTORY == true ]] && echo -n 0 || echo -n 1)
|
||||||
|
sync-git-verify-commit-signature = yes
|
||||||
|
sync-openpgp-key-path = /usr/share/openpgp-keys/gentoo-release.asc
|
||||||
|
EOF
|
||||||
|
chmod 644 /etc/portage/repos.conf/gentoo.conf \
|
||||||
|
|| die "Could not change permissions of '/etc/portage/repos.conf/gentoo.conf'"
|
||||||
|
rm -rf /var/db/repos/gentoo \
|
||||||
|
|| die "Could not delete obsolete rsync gentoo repository"
|
||||||
|
try emerge --sync
|
||||||
|
fi
|
||||||
|
maybe_exec 'after_configure_portage'
|
||||||
|
|
||||||
|
einfo "Generating ssh host keys"
|
||||||
|
try ssh-keygen -A
|
||||||
|
|
||||||
|
# Install authorized_keys before dracut, which might need them for remote unlocking.
|
||||||
|
install_authorized_keys
|
||||||
|
|
||||||
|
einfo "Enabling dracut USE flag on sys-kernel/installkernel"
|
||||||
|
echo "sys-kernel/installkernel dracut" > /etc/portage/package.use/installkernel \
|
||||||
|
|| die "Could not write /etc/portage/package.use/installkernel"
|
||||||
|
|
||||||
|
# Install required programs and kernel now, in order to
|
||||||
|
# prevent emerging module before an imminent kernel upgrade
|
||||||
|
try emerge --verbose sys-kernel/dracut sys-kernel/gentoo-kernel-bin app-arch/zstd
|
||||||
|
|
||||||
|
# Install mdadm if we used raid (needed for uuid resolving)
|
||||||
|
if [[ $USED_RAID == "true" ]]; then
|
||||||
|
einfo "Installing mdadm"
|
||||||
|
try emerge --verbose sys-fs/mdadm
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Install cryptsetup if we used luks
|
||||||
|
if [[ $USED_LUKS == "true" ]]; then
|
||||||
|
einfo "Installing cryptsetup"
|
||||||
|
try emerge --verbose sys-fs/cryptsetup
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [[ $SYSTEMD == "true" && $USED_LUKS == "true" ]] ; then
|
||||||
|
einfo "Enabling cryptsetup USE flag on sys-apps/systemd"
|
||||||
|
echo "sys-apps/systemd cryptsetup" > /etc/portage/package.use/systemd \
|
||||||
|
|| die "Could not write /etc/portage/package.use/systemd"
|
||||||
|
einfo "Rebuilding systemd with changed USE flag"
|
||||||
|
try emerge --verbose --changed-use --oneshot sys-apps/systemd
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Install btrfs-progs if we used btrfs
|
||||||
|
if [[ $USED_BTRFS == "true" ]]; then
|
||||||
|
einfo "Installing btrfs-progs"
|
||||||
|
try emerge --verbose sys-fs/btrfs-progs
|
||||||
|
fi
|
||||||
|
|
||||||
|
try emerge --verbose dev-vcs/git
|
||||||
|
|
||||||
|
# Install zfs kernel module and tools if we used zfs
|
||||||
|
if [[ $USED_ZFS == "true" ]]; then
|
||||||
|
einfo "Installing zfs"
|
||||||
|
try emerge --verbose sys-fs/zfs sys-fs/zfs-kmod
|
||||||
|
|
||||||
|
einfo "Enabling zfs services"
|
||||||
|
if [[ $SYSTEMD == "true" ]]; then
|
||||||
|
try systemctl enable zfs.target
|
||||||
|
try systemctl enable zfs-import-cache
|
||||||
|
try systemctl enable zfs-mount
|
||||||
|
try systemctl enable zfs-import.target
|
||||||
|
else
|
||||||
|
try rc-update add zfs-import boot
|
||||||
|
try rc-update add zfs-mount boot
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Install kernel and initramfs
|
||||||
|
maybe_exec 'before_install_kernel'
|
||||||
|
install_kernel
|
||||||
|
maybe_exec 'after_install_kernel'
|
||||||
|
|
||||||
|
# Generate a valid fstab file
|
||||||
|
generate_fstab
|
||||||
|
|
||||||
|
# Install gentoolkit
|
||||||
|
einfo "Installing gentoolkit"
|
||||||
|
try emerge --verbose app-portage/gentoolkit
|
||||||
|
|
||||||
|
if [[ $SYSTEMD == "true" ]]; then
|
||||||
|
if [[ $SYSTEMD_NETWORKD == "true" ]]; then
|
||||||
|
# Enable systemd networking and dhcp
|
||||||
|
enable_service systemd-networkd
|
||||||
|
enable_service systemd-resolved
|
||||||
|
if [[ $SYSTEMD_NETWORKD_DHCP == "true" ]]; then
|
||||||
|
echo -en "[Match]\nName=${SYSTEMD_NETWORKD_INTERFACE_NAME}\n\n[Network]\nDHCP=yes" > /etc/systemd/network/20-wired.network \
|
||||||
|
|| die "Could not write dhcp network config to '/etc/systemd/network/20-wired.network'"
|
||||||
|
else
|
||||||
|
addresses=""
|
||||||
|
for addr in "${SYSTEMD_NETWORKD_ADDRESSES[@]}"; do
|
||||||
|
addresses="${addresses}Address=$addr\n"
|
||||||
|
done
|
||||||
|
echo -en "[Match]\nName=${SYSTEMD_NETWORKD_INTERFACE_NAME}\n\n[Network]\n${addresses}Gateway=$SYSTEMD_NETWORKD_GATEWAY" > /etc/systemd/network/20-wired.network \
|
||||||
|
|| die "Could not write dhcp network config to '/etc/systemd/network/20-wired.network'"
|
||||||
|
fi
|
||||||
|
chown root:systemd-network /etc/systemd/network/20-wired.network \
|
||||||
|
|| die "Could not change owner of '/etc/systemd/network/20-wired.network'"
|
||||||
|
chmod 640 /etc/systemd/network/20-wired.network \
|
||||||
|
|| die "Could not change permissions of '/etc/systemd/network/20-wired.network'"
|
||||||
|
fi
|
||||||
|
else
|
||||||
|
# Install and enable dhcpcd
|
||||||
|
einfo "Installing dhcpcd"
|
||||||
|
try emerge --verbose net-misc/dhcpcd
|
||||||
|
|
||||||
|
enable_service dhcpcd
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [[ $ENABLE_SSHD == "true" ]]; then
|
||||||
|
enable_sshd
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Install additional packages, if any.
|
||||||
|
if [[ ${#ADDITIONAL_PACKAGES[@]} -gt 0 ]]; then
|
||||||
|
einfo "Installing additional packages"
|
||||||
|
# shellcheck disable=SC2086
|
||||||
|
try emerge --verbose --autounmask-continue=y -- "${ADDITIONAL_PACKAGES[@]}"
|
||||||
|
fi
|
||||||
|
|
||||||
|
if ask "Do you want to assign a root password now?"; then
|
||||||
|
try passwd root
|
||||||
|
einfo "Root password assigned"
|
||||||
|
else
|
||||||
|
try passwd -d root
|
||||||
|
ewarn "Root password cleared, set one as soon as possible!"
|
||||||
|
fi
|
||||||
|
|
||||||
|
# If configured, change to gentoo testing at the last moment.
|
||||||
|
# This is to ensure a smooth installation process. You can deal
|
||||||
|
# with the blockers after installation ;)
|
||||||
|
if [[ $USE_PORTAGE_TESTING == "true" ]]; then
|
||||||
|
einfo "Adding ~$GENTOO_ARCH to ACCEPT_KEYWORDS"
|
||||||
|
echo "ACCEPT_KEYWORDS=\"~$GENTOO_ARCH\"" >> /etc/portage/make.conf \
|
||||||
|
|| die "Could not modify /etc/portage/make.conf"
|
||||||
|
fi
|
||||||
|
|
||||||
|
maybe_exec 'after_install'
|
||||||
|
|
||||||
|
einfo "Gentoo installation complete."
|
||||||
|
[[ $USED_LUKS == "true" ]] \
|
||||||
|
&& einfo "A backup of your luks headers can be found at '$LUKS_HEADER_BACKUP_DIR', in case you want to have a backup."
|
||||||
|
einfo "You may now reboot your system or execute ./install --chroot $ROOT_MOUNTPOINT to enter your system in a chroot."
|
||||||
|
einfo "Chrooting in this way is always possible in case you need to fix something after rebooting."
|
||||||
|
}
|
||||||
|
|
||||||
|
function main_install() {
|
||||||
|
[[ $# == 0 ]] || die "Too many arguments"
|
||||||
|
|
||||||
|
gentoo_umount
|
||||||
|
install_stage3
|
||||||
|
|
||||||
|
[[ $IS_EFI == "true" ]] \
|
||||||
|
&& mount_efivars
|
||||||
|
gentoo_chroot "$ROOT_MOUNTPOINT" "$GENTOO_INSTALL_REPO_BIND/install" __install_gentoo_in_chroot
|
||||||
|
}
|
||||||
|
|
||||||
|
function main_chroot() {
|
||||||
|
# Skip if already mounted
|
||||||
|
mountpoint -q -- "$1" \
|
||||||
|
|| die "'$1' is not a mountpoint"
|
||||||
|
|
||||||
|
gentoo_chroot "$@"
|
||||||
|
}
|
4
scripts/protection.sh
Normal file
4
scripts/protection.sh
Normal file
|
@ -0,0 +1,4 @@
|
||||||
|
if [[ "$GENTOO_INSTALL_REPO_SCRIPT_ACTIVE" != "true" ]]; then
|
||||||
|
echo "[1;31m * ERROR:[m This script must not be executed directly!" >&2
|
||||||
|
exit 1
|
||||||
|
fi
|
453
scripts/utils.sh
Normal file
453
scripts/utils.sh
Normal file
|
@ -0,0 +1,453 @@
|
||||||
|
# shellcheck source=./scripts/protection.sh
|
||||||
|
source "$GENTOO_INSTALL_REPO_DIR/scripts/protection.sh" || exit 1
|
||||||
|
|
||||||
|
function elog() {
|
||||||
|
echo "[[1m+[m] $*"
|
||||||
|
}
|
||||||
|
|
||||||
|
function einfo() {
|
||||||
|
echo "[[1m+[m] [1;33m$*[m"
|
||||||
|
}
|
||||||
|
|
||||||
|
function ewarn() {
|
||||||
|
echo "[[1;31m![m] [1;33m$*[m" >&2
|
||||||
|
}
|
||||||
|
|
||||||
|
function eerror() {
|
||||||
|
echo "[1;31merror:[m $*" >&2
|
||||||
|
}
|
||||||
|
|
||||||
|
function die() {
|
||||||
|
eerror "$*"
|
||||||
|
[[ -v GENTOO_INSTALL_REPO_SCRIPT_PID && $$ -ne $GENTOO_INSTALL_REPO_SCRIPT_PID ]] \
|
||||||
|
&& kill "$GENTOO_INSTALL_REPO_SCRIPT_PID"
|
||||||
|
exit 1
|
||||||
|
}
|
||||||
|
|
||||||
|
# Prints an error with file:line info of the nth "stack frame".
|
||||||
|
# 0 is this function, 1 the calling function, 2 its parent, and so on.
|
||||||
|
function die_trace() {
|
||||||
|
local idx="${1:-0}"
|
||||||
|
shift
|
||||||
|
echo "[1m${BASH_SOURCE[$((idx + 1))]}:${BASH_LINENO[$idx]}: [1;31merror:[m ${FUNCNAME[$idx]}: $*" >&2
|
||||||
|
exit 1
|
||||||
|
}
|
||||||
|
|
||||||
|
function for_line_in() {
|
||||||
|
while IFS="" read -r line || [[ -n $line ]]; do
|
||||||
|
"$2" "$line"
|
||||||
|
done <"$1"
|
||||||
|
}
|
||||||
|
|
||||||
|
function flush_stdin() {
|
||||||
|
local empty_stdin
|
||||||
|
# Unused variable is intentional.
|
||||||
|
# shellcheck disable=SC2034
|
||||||
|
while read -r -t 0.01 empty_stdin; do true; done
|
||||||
|
}
|
||||||
|
|
||||||
|
function ask() {
|
||||||
|
local response
|
||||||
|
while true; do
|
||||||
|
flush_stdin
|
||||||
|
read -r -p "$* (Y/n) " response \
|
||||||
|
|| die "Error in read"
|
||||||
|
case "${response,,}" in
|
||||||
|
'') return 0 ;;
|
||||||
|
y|yes) return 0 ;;
|
||||||
|
n|no) return 1 ;;
|
||||||
|
*) continue ;;
|
||||||
|
esac
|
||||||
|
done
|
||||||
|
}
|
||||||
|
|
||||||
|
function try() {
|
||||||
|
local response
|
||||||
|
local cmd_status
|
||||||
|
local prompt_parens="([1mS[mhell/[1mr[metry/[1ma[mbort/[1mc[montinue/[1mp[mrint)"
|
||||||
|
|
||||||
|
# Outer loop, allows us to retry the command
|
||||||
|
while true; do
|
||||||
|
# Try command
|
||||||
|
"$@"
|
||||||
|
cmd_status="$?"
|
||||||
|
|
||||||
|
if [[ $cmd_status != 0 ]]; then
|
||||||
|
echo "[1;31m * Command failed: [1;33m\$[m $*"
|
||||||
|
echo "Last command failed with exit code $cmd_status"
|
||||||
|
|
||||||
|
# Prompt until input is valid
|
||||||
|
while true; do
|
||||||
|
echo -n "Specify next action $prompt_parens "
|
||||||
|
flush_stdin
|
||||||
|
read -r response \
|
||||||
|
|| die "Error in read"
|
||||||
|
case "${response,,}" in
|
||||||
|
''|s|shell)
|
||||||
|
echo "You will be prompted for action again after exiting this shell."
|
||||||
|
/bin/bash --init-file <(echo "init_bash")
|
||||||
|
;;
|
||||||
|
r|retry) continue 2 ;;
|
||||||
|
a|abort) die "Installation aborted" ;;
|
||||||
|
c|continue) return 0 ;;
|
||||||
|
p|print) echo "[1;33m\$[m $*" ;;
|
||||||
|
*) ;;
|
||||||
|
esac
|
||||||
|
done
|
||||||
|
fi
|
||||||
|
|
||||||
|
return
|
||||||
|
done
|
||||||
|
}
|
||||||
|
|
||||||
|
function countdown() {
|
||||||
|
echo -n "$1" >&2
|
||||||
|
|
||||||
|
local i="$2"
|
||||||
|
while [[ $i -gt 0 ]]; do
|
||||||
|
echo -n "[1;31m$i[m " >&2
|
||||||
|
i=$((i - 1))
|
||||||
|
sleep 1
|
||||||
|
done
|
||||||
|
echo >&2
|
||||||
|
}
|
||||||
|
|
||||||
|
function download_stdout() {
|
||||||
|
wget --quiet --https-only --secure-protocol=PFS -O - -- "$1"
|
||||||
|
}
|
||||||
|
|
||||||
|
function download() {
|
||||||
|
wget --quiet --https-only --secure-protocol=PFS --show-progress -O "$2" -- "$1"
|
||||||
|
}
|
||||||
|
|
||||||
|
function get_blkid_field_by_device() {
|
||||||
|
local blkid_field="$1"
|
||||||
|
local device="$2"
|
||||||
|
blkid -g -c /dev/null \
|
||||||
|
|| die "Error while executing blkid"
|
||||||
|
partprobe &>/dev/null
|
||||||
|
local val
|
||||||
|
val="$(blkid -c /dev/null -o export "$device")" \
|
||||||
|
|| die "Error while executing blkid '$device'"
|
||||||
|
val="$(grep -- "^$blkid_field=" <<< "$val")" \
|
||||||
|
|| die "Could not find $blkid_field=... in blkid output"
|
||||||
|
val="${val#"$blkid_field="}"
|
||||||
|
echo -n "$val"
|
||||||
|
}
|
||||||
|
|
||||||
|
function get_blkid_uuid_for_id() {
|
||||||
|
local dev
|
||||||
|
dev="$(resolve_device_by_id "$1")" \
|
||||||
|
|| die "Could not resolve device with id=$dev"
|
||||||
|
local uuid
|
||||||
|
uuid="$(get_blkid_field_by_device 'UUID' "$dev")" \
|
||||||
|
|| die "Could not get UUID from blkid for device=$dev"
|
||||||
|
echo -n "$uuid"
|
||||||
|
}
|
||||||
|
|
||||||
|
function get_device_by_blkid_field() {
|
||||||
|
local blkid_field="$1"
|
||||||
|
local field_value="$2"
|
||||||
|
blkid -g -c /dev/null \
|
||||||
|
|| die "Error while executing blkid"
|
||||||
|
type partprobe &>/dev/null && partprobe &>/dev/null
|
||||||
|
local dev
|
||||||
|
dev="$(blkid -c /dev/null -o export -t "$blkid_field=$field_value")" \
|
||||||
|
|| die "Error while executing blkid to find $blkid_field=$field_value"
|
||||||
|
dev="$(grep DEVNAME <<< "$dev")" \
|
||||||
|
|| die "Could not find DEVNAME=... in blkid output"
|
||||||
|
dev="${dev#"DEVNAME="}"
|
||||||
|
echo -n "$dev"
|
||||||
|
}
|
||||||
|
|
||||||
|
function get_device_by_partuuid() {
|
||||||
|
if [[ -e "/dev/disk/by-partuuid/$1" ]]; then
|
||||||
|
echo -n "/dev/disk/by-partuuid/$1"
|
||||||
|
else
|
||||||
|
get_device_by_blkid_field 'PARTUUID' "$1"
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
function get_device_by_uuid() {
|
||||||
|
if [[ -e "/dev/disk/by-uuid/$1" ]]; then
|
||||||
|
echo -n "/dev/disk/by-uuid/$1"
|
||||||
|
else
|
||||||
|
get_device_by_blkid_field 'UUID' "$1"
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
function cache_lsblk_output() {
|
||||||
|
CACHED_LSBLK_OUTPUT="$(lsblk --all --path --pairs --output NAME,PTUUID,PARTUUID)" \
|
||||||
|
|| die "Error while executing lsblk to cache output"
|
||||||
|
}
|
||||||
|
|
||||||
|
function get_device_by_ptuuid() {
|
||||||
|
local ptuuid="${1,,}"
|
||||||
|
local dev
|
||||||
|
if [[ -v CACHED_LSBLK_OUTPUT && -n "$CACHED_LSBLK_OUTPUT" ]]; then
|
||||||
|
dev="$CACHED_LSBLK_OUTPUT"
|
||||||
|
else
|
||||||
|
dev="$(lsblk --all --path --pairs --output NAME,PTUUID,PARTUUID)" \
|
||||||
|
|| die "Error while executing lsblk to find PTUUID=$ptuuid"
|
||||||
|
fi
|
||||||
|
dev="$(grep "ptuuid=\"$ptuuid\" partuuid=\"\"" <<< "${dev,,}")" \
|
||||||
|
|| die "Could not find PTUUID=... in lsblk output"
|
||||||
|
dev="${dev%'" ptuuid='*}"
|
||||||
|
dev="${dev#'name="'}"
|
||||||
|
echo -n "$dev"
|
||||||
|
}
|
||||||
|
|
||||||
|
function uuid_to_mduuid() {
|
||||||
|
local mduuid="${1,,}"
|
||||||
|
mduuid="${mduuid//-/}"
|
||||||
|
mduuid="${mduuid:0:8}:${mduuid:8:8}:${mduuid:16:8}:${mduuid:24:8}"
|
||||||
|
echo -n "$mduuid"
|
||||||
|
}
|
||||||
|
|
||||||
|
function get_device_by_mdadm_uuid() {
|
||||||
|
local mduuid
|
||||||
|
mduuid="$(uuid_to_mduuid "$1")" \
|
||||||
|
|| die "Could not resolve mduuid from uuid=$1"
|
||||||
|
local dev
|
||||||
|
dev="$(mdadm --examine --scan)" \
|
||||||
|
|| die "Error while executing mdadm to find array with UUID=$mduuid"
|
||||||
|
dev="$(grep "uuid=$mduuid" <<< "${dev,,}")" \
|
||||||
|
|| die "Could not find UUID=... in mdadm output"
|
||||||
|
dev="${dev%'metadata='*}"
|
||||||
|
dev="${dev#'array'}"
|
||||||
|
dev="${dev#"${dev%%[![:space:]]*}"}"
|
||||||
|
dev="${dev%"${dev##*[![:space:]]}"}"
|
||||||
|
echo -n "$dev"
|
||||||
|
}
|
||||||
|
|
||||||
|
function get_device_by_luks_name() {
|
||||||
|
echo -n "/dev/mapper/$1"
|
||||||
|
}
|
||||||
|
|
||||||
|
function create_resolve_entry() {
|
||||||
|
local id="$1"
|
||||||
|
local type="$2"
|
||||||
|
local arg="${3,,}"
|
||||||
|
|
||||||
|
DISK_ID_TO_RESOLVABLE[$id]="$type:$arg"
|
||||||
|
}
|
||||||
|
|
||||||
|
function create_resolve_entry_device() {
|
||||||
|
local id="$1"
|
||||||
|
local dev="$2"
|
||||||
|
|
||||||
|
DISK_ID_TO_RESOLVABLE[$id]="device:$dev"
|
||||||
|
}
|
||||||
|
|
||||||
|
# Returns the basename of the device, if its path starts with /dev/disk/by-id/
|
||||||
|
function shorten_device() {
|
||||||
|
echo -n "${1#/dev/disk/by-id/}"
|
||||||
|
}
|
||||||
|
|
||||||
|
# Return matching device from /dev/disk/by-id/ if possible,
|
||||||
|
# otherwise return the parameter unchanged.
|
||||||
|
function canonicalize_device() {
|
||||||
|
given_dev="$(realpath "$1")"
|
||||||
|
for dev in /dev/disk/by-id/*; do
|
||||||
|
if [[ "$(realpath "$dev")" == "$given_dev" ]]; then
|
||||||
|
echo -n "$dev"
|
||||||
|
return 0
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
|
||||||
|
echo -n "$1"
|
||||||
|
}
|
||||||
|
|
||||||
|
function resolve_device_by_id() {
|
||||||
|
local id="$1"
|
||||||
|
[[ -v DISK_ID_TO_RESOLVABLE[$id] ]] \
|
||||||
|
|| die "Cannot resolve id='$id' to a block device (no table entry)"
|
||||||
|
|
||||||
|
local type="${DISK_ID_TO_RESOLVABLE[$id]%%:*}"
|
||||||
|
local arg="${DISK_ID_TO_RESOLVABLE[$id]#*:}"
|
||||||
|
|
||||||
|
local dev
|
||||||
|
case "$type" in
|
||||||
|
'partuuid') dev=$(get_device_by_partuuid "$arg") ;;
|
||||||
|
'ptuuid') dev=$(get_device_by_ptuuid "$arg") ;;
|
||||||
|
'uuid') dev=$(get_device_by_uuid "$arg") ;;
|
||||||
|
'mdadm') dev=$(get_device_by_mdadm_uuid "$arg") ;;
|
||||||
|
'luks') dev=$(get_device_by_luks_name "$arg") ;;
|
||||||
|
'device') dev="$arg" ;;
|
||||||
|
*) die "Cannot resolve '$type:$arg' to device (unknown type)"
|
||||||
|
esac
|
||||||
|
|
||||||
|
canonicalize_device "$dev"
|
||||||
|
}
|
||||||
|
|
||||||
|
function load_or_generate_uuid() {
|
||||||
|
local uuid
|
||||||
|
local uuid_file="$UUID_STORAGE_DIR/$1"
|
||||||
|
|
||||||
|
if [[ -e $uuid_file ]]; then
|
||||||
|
uuid="$(cat "$uuid_file")"
|
||||||
|
else
|
||||||
|
uuid="$(uuidgen -r)"
|
||||||
|
mkdir -p "$UUID_STORAGE_DIR"
|
||||||
|
echo -n "$uuid" > "$uuid_file"
|
||||||
|
fi
|
||||||
|
|
||||||
|
echo -n "$uuid"
|
||||||
|
}
|
||||||
|
|
||||||
|
# Parses named arguments and stores them in the associative array `arguments`.
|
||||||
|
# If given, the associative array `known_arguments` must contain a list of arguments
|
||||||
|
# prefixed with + (mandatory) or ? (optional). "at least one of" can be expressed by +a|b|c.
|
||||||
|
function parse_arguments() {
|
||||||
|
local key
|
||||||
|
local value
|
||||||
|
local a
|
||||||
|
for a in "$@"; do
|
||||||
|
key="${a%%=*}"
|
||||||
|
value="${a#*=}"
|
||||||
|
|
||||||
|
if [[ $key == "$a" ]]; then
|
||||||
|
extra_arguments+=("$a")
|
||||||
|
continue
|
||||||
|
fi
|
||||||
|
|
||||||
|
arguments[$key]="$value"
|
||||||
|
done
|
||||||
|
|
||||||
|
declare -A allowed_keys
|
||||||
|
if [[ -v known_arguments ]]; then
|
||||||
|
local m
|
||||||
|
for m in "${known_arguments[@]}"; do
|
||||||
|
case "${m:0:1}" in
|
||||||
|
'+')
|
||||||
|
m="${m:1}"
|
||||||
|
local has_opt=false
|
||||||
|
local m_opt
|
||||||
|
# Splitting is intentional here
|
||||||
|
# shellcheck disable=SC2086
|
||||||
|
for m_opt in ${m//|/ }; do
|
||||||
|
allowed_keys[$m_opt]=true
|
||||||
|
if [[ -v arguments[$m_opt] ]]; then
|
||||||
|
has_opt=true
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
|
||||||
|
[[ $has_opt == "true" ]] \
|
||||||
|
|| die_trace 2 "Missing mandatory argument $m=..."
|
||||||
|
;;
|
||||||
|
|
||||||
|
'?')
|
||||||
|
allowed_keys[${m:1}]=true
|
||||||
|
;;
|
||||||
|
|
||||||
|
*) die_trace 2 "Invalid start character in known_arguments, in argument '$m'" ;;
|
||||||
|
esac
|
||||||
|
done
|
||||||
|
|
||||||
|
for a in "${!arguments[@]}"; do
|
||||||
|
[[ -v allowed_keys[$a] ]] \
|
||||||
|
|| die_trace 2 "Unknown argument '$a'"
|
||||||
|
done
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
# $1: program
|
||||||
|
# $2: checkfile
|
||||||
|
function has_program() {
|
||||||
|
local program="$1"
|
||||||
|
local checkfile="$2"
|
||||||
|
if [[ -z "$checkfile" ]]; then
|
||||||
|
type "$program" &>/dev/null \
|
||||||
|
|| return 1
|
||||||
|
elif [[ "${checkfile:0:1}" == "/" ]]; then
|
||||||
|
[[ -e "$checkfile" ]] \
|
||||||
|
|| return 1
|
||||||
|
else
|
||||||
|
type "$checkfile" &>/dev/null \
|
||||||
|
|| return 1
|
||||||
|
fi
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
|
||||||
|
function check_wanted_programs() {
|
||||||
|
local missing_required=()
|
||||||
|
local missing_wanted=()
|
||||||
|
local tuple
|
||||||
|
local program
|
||||||
|
local checkfile
|
||||||
|
for tuple in "$@"; do
|
||||||
|
program="${tuple%%=*}"
|
||||||
|
checkfile=""
|
||||||
|
[[ "$tuple" == *=* ]] \
|
||||||
|
&& checkfile="${tuple##*=}"
|
||||||
|
if ! has_program "${program#"?"}" "$checkfile"; then
|
||||||
|
if [[ "$program" == "?"* ]]; then
|
||||||
|
missing_wanted+=("${program#"?"}")
|
||||||
|
else
|
||||||
|
missing_required+=("$program")
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
|
||||||
|
[[ "${#missing_required[@]}" -eq 0 && "${#missing_wanted[@]}" -eq 0 ]] \
|
||||||
|
&& return
|
||||||
|
|
||||||
|
if [[ "${#missing_required[@]}" -gt 0 ]]; then
|
||||||
|
elog "The following programs are required for the installer to work, but are currently missing on your system:" >&2
|
||||||
|
elog " ${missing_required[*]}" >&2
|
||||||
|
fi
|
||||||
|
if [[ "${#missing_wanted[@]}" -gt 0 ]]; then
|
||||||
|
elog "Missing optional programs:" >&2
|
||||||
|
elog " ${missing_wanted[*]}" >&2
|
||||||
|
fi
|
||||||
|
|
||||||
|
if type pacman &>/dev/null; then
|
||||||
|
declare -A pacman_packages
|
||||||
|
pacman_packages=(
|
||||||
|
[ntpd]=ntp
|
||||||
|
[zfs]=""
|
||||||
|
)
|
||||||
|
elog "Detected pacman package manager."
|
||||||
|
if ask "Do you want to install all missing programs automatically?"; then
|
||||||
|
local packages
|
||||||
|
local need_zfs=false
|
||||||
|
|
||||||
|
for program in "${missing_required[@]}" "${missing_wanted[@]}"; do
|
||||||
|
[[ "$program" == "zfs" ]] \
|
||||||
|
&& need_zfs=true
|
||||||
|
|
||||||
|
if [[ -v "pacman_packages[$program]" ]]; then
|
||||||
|
# Assignments to the empty string are explicitly ignored,
|
||||||
|
# as for example, zfs needs to be handled separately.
|
||||||
|
[[ -n "${pacman_packages[$program]}" ]] \
|
||||||
|
&& packages+=("${pacman_packages[$program]}")
|
||||||
|
else
|
||||||
|
packages+=("$program")
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
pacman -Sy "${packages[@]}"
|
||||||
|
|
||||||
|
if [[ "$need_zfs" == true ]]; then
|
||||||
|
elog "On an Arch live-stick you need the archzfs repository and some tools and modifications to use zfs."
|
||||||
|
elog "There is an automated installer available at https://raw.githubusercontent.com/eoli3n/archiso-zfs/master/init."
|
||||||
|
if ask "Do you want to automatically download and execute this zfs installation script?"; then
|
||||||
|
curl -s "https://raw.githubusercontent.com/eoli3n/archiso-zfs/master/init" | bash
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
|
||||||
|
return
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [[ "${#missing_required[@]}" -gt 0 ]]; then
|
||||||
|
die "Aborted installer because of missing required programs."
|
||||||
|
else
|
||||||
|
ask "Continue without recommended programs?"
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
# exec function if defined
|
||||||
|
# $@ function name and arguments
|
||||||
|
function maybe_exec() {
|
||||||
|
type "$1" &>/dev/null && "$@"
|
||||||
|
}
|
19
tests/create-vm-gentoo.sh
Executable file
19
tests/create-vm-gentoo.sh
Executable file
|
@ -0,0 +1,19 @@
|
||||||
|
#!/bin/bash
|
||||||
|
|
||||||
|
virt-install \
|
||||||
|
--connect=qemu:///system \
|
||||||
|
--name=vm-gentoo \
|
||||||
|
--vcpus=2 \
|
||||||
|
--memory=2048 \
|
||||||
|
--cdrom=/vm/images/archlinux-2021.05.01-x86_64.iso \
|
||||||
|
--disk path=/vm/disks/disk-vm-gentoo.disk,size=25 \
|
||||||
|
--boot uefi \
|
||||||
|
--os-variant=gentoo \
|
||||||
|
--noautoconsole
|
||||||
|
# --transient \
|
||||||
|
# --graphics none \
|
||||||
|
# --console pty,target.type=virtio \
|
||||||
|
# --serial pty \
|
||||||
|
# --extra-args 'console=ttyS0,115200n8 --- console=ttyS0,115200n8' \
|
||||||
|
|
||||||
|
# virsh
|
19
tests/shellcheck.sh
Executable file
19
tests/shellcheck.sh
Executable file
|
@ -0,0 +1,19 @@
|
||||||
|
#!/bin/bash
|
||||||
|
|
||||||
|
# Find the directory this script is stored in. (from: http://stackoverflow.com/questions/59895)
|
||||||
|
function get_source_dir() {
|
||||||
|
local source="${BASH_SOURCE[0]}"
|
||||||
|
while [[ -h $source ]]
|
||||||
|
do
|
||||||
|
local tmp
|
||||||
|
tmp="$(cd -P "$(dirname "${source}")" && pwd)"
|
||||||
|
source="$(readlink "${source}")"
|
||||||
|
[[ $source != /* ]] && source="${tmp}/${source}"
|
||||||
|
done
|
||||||
|
|
||||||
|
echo -n "$(realpath "$(dirname "${source}")")"
|
||||||
|
}
|
||||||
|
|
||||||
|
cd "$(get_source_dir)/.."
|
||||||
|
shellcheck -s bash --check-sourced --external-sources ./install
|
||||||
|
shellcheck -s bash --check-sourced --external-sources ./configure
|
Loading…
Reference in a new issue