"""Generate fstab and crypttab configuration files.""" from pathlib import Path from .utils import info, success, run_quiet from .disk import DiskLayout, DiskConfig def get_uuid(device: Path) -> str: """Get UUID of a block device.""" result = run_quiet("blkid", "-s", "UUID", "-o", "value", str(device)) return result.stdout.strip() def get_luks_uuid(device: Path) -> str: """Get UUID of a LUKS container.""" return get_uuid(device) def generate_fstab( layout: DiskLayout, config: DiskConfig, mount_root: Path | None = None, ) -> None: """Generate /etc/fstab for the new system.""" if mount_root is None: mount_root = config.mount_root info("Generating /etc/fstab...") efi_uuid = get_uuid(layout.part_efi) mapper = config.mapper_path opts = config.btrfs_opts fstab_content = f"""\ # /etc/fstab - Generated by install-installer v4 # Legion S7 with LUKS encryption + Btrfs subvolumes # EFI System Partition UUID={efi_uuid} /boot vfat noatime,defaults 0 2 # Encrypted swap - NOTE: This entry is NOT used by swapon directly. # Swap activation is handled by the OpenRC dmcrypt service (/etc/conf.d/dmcrypt) # which creates /dev/mapper/swap with a random key at boot. {layout.part_swap} none swap sw,cipher=aes-xts-plain64,size=256 0 0 # Btrfs on LUKS ({config.mapper_name}) {mapper} / btrfs {opts},subvol=@ 0 0 {mapper} /home btrfs {opts},subvol=@home 0 0 {mapper} /var btrfs {opts},subvol=@var 0 0 {mapper} /var/log btrfs {opts},subvol=@log 0 0 {mapper} /.snapshots btrfs {opts},subvol=@snapshots 0 0 """ fstab_path = mount_root / "etc/fstab" fstab_path.write_text(fstab_content) success(f"Generated {fstab_path}") def generate_crypttab( layout: DiskLayout, config: DiskConfig, mount_root: Path | None = None, ) -> None: """Generate /etc/crypttab for the new system.""" if mount_root is None: mount_root = config.mount_root info("Generating /etc/crypttab...") luks_uuid = get_luks_uuid(layout.part_root) crypttab_content = f"""\ # /etc/crypttab - Generated by install-installer v4 # LUKS root partition {config.mapper_name} UUID={luks_uuid} none luks """ crypttab_path = mount_root / "etc/crypttab" crypttab_path.write_text(crypttab_content) success(f"Generated {crypttab_path}") def generate_dmcrypt_conf( layout: DiskLayout, mount_root: Path | None = None, ) -> None: """Generate /etc/conf.d/dmcrypt for OpenRC encrypted swap.""" if mount_root is None: mount_root = Path("/mnt/gentoo") info("Generating /etc/conf.d/dmcrypt...") dmcrypt_content = f"""\ # /etc/conf.d/dmcrypt - Generated by install-installer v4 # Encrypted swap with random key (no hibernate support) swap=swap source='{layout.part_swap}' """ dmcrypt_path = mount_root / "etc/conf.d/dmcrypt" dmcrypt_path.parent.mkdir(parents=True, exist_ok=True) dmcrypt_path.write_text(dmcrypt_content) success(f"Generated {dmcrypt_path}") def generate_all( layout: DiskLayout, config: DiskConfig, mount_root: Path | None = None, ) -> None: """Generate all filesystem configuration files.""" if mount_root is None: mount_root = config.mount_root generate_fstab(layout, config, mount_root) generate_crypttab(layout, config, mount_root) generate_dmcrypt_conf(layout, mount_root) print() success("=== Filesystem configuration complete ===")