# -*- coding: utf-8 -*- """ SPDX-FileCopyrightText: 2023-2025 PeppermintOS Team (peppermintosteam@proton.me) SPDX-License-Identifier: GPL-3.0-or-later This module is responsible for creating a SquashFS image from the root filesystem directory. It utilizes the `mksquashfs` utility found within the PEPHOSTDIR to generate a compressed read-only filesystem image that will be used in the PeppermintOS ISO. The module handles the process of determining the required size, creating a temporary ext3 filesystem, copying the root filesystem to it, unmounting, and then using `mksquashfs` to create the final image. Temporary directories are cleaned up after the process is complete. Credits: - PeppermintOS Team (peppermintosteam@proton.me) - Development and maintenance of the project. License: This code is distributed under the GNU General Public License version 3 or later (GPL-3.0-or-later). For more details, please refer to the LICENSE file included in the project or visit: https://www.gnu.org/licenses/gpl-3.0.html """ import subprocess import logging import os import sys import tempfile import shutil BASE_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__))) sys.path.insert(0, BASE_DIR) try: from builder.core.bootstrap.paths import paths from builder.core.command_runner import run_command from builder.configs import logger_config logger = logger_config.setup_logger('squashfs') # Pass the 'squashfs' argument except ImportError as e: print(f"Error importing necessary modules: {e}. Ensure your environment is set up correctly.") sys.exit(1) def create_squashfs_image(rootfs_dir, squashfs_output_file, pep_host_dir, logger): """ Initiates the creation of the SquashFS image using mksquashfs from PEPHOSTDIR. Args: rootfs_dir (str): The path to the root filesystem directory. squashfs_output_file (str): The desired path for the output SquashFS image file. pep_host_dir (str): The path to the PEPHOSTDIR, which should contain the mksquashfs utility. logger (logging.Logger): The logger instance to use for logging messages. Returns: str or None: The path to the created SquashFS image file if successful, otherwise None. """ logger.info("=> Initiating SquashFS image creation using mksquashfs from PEPHOSTDIR...") logger.info(f"=> Source ROOTFS directory: {rootfs_dir}") logger.info(f"=> Output SquashFS file: {squashfs_output_file}") logger.info(f"=> PEPHOSTDIR: {pep_host_dir}") build_dir = paths['BUILDDIR'] image_dir = paths['IMAGEDIR'] liveos_tmp_dir = os.path.join(build_dir, "tmp", "LiveOS") temp_rootfs_mount_dir = os.path.join(build_dir, "tmp-rootfs") os.makedirs(liveos_tmp_dir, exist_ok=True) os.makedirs(temp_rootfs_mount_dir, exist_ok=True) try: # Find out required size for the rootfs rootfs_size_command = ["du", "--apparent-size", "-sm", rootfs_dir] result = run_command(rootfs_size_command) if result.returncode != 0: logger.error(f"Error getting ROOTFS size: {result.stderr.strip()}") return None rootfs_size_mb = int(result.stdout.split()[0]) ext3_image_size_mb = 2 * rootfs_size_mb # Double the size ext3_image_file = os.path.join(liveos_tmp_dir, "ext3fs.img") truncate_command = ["truncate", "-s", f"{ext3_image_size_mb}M", ext3_image_file] run_command(truncate_command) mkfs_command = ["mkfs.ext3", "-F", "-m1", ext3_image_file] run_command(mkfs_command) mount_command = ["mount", "-o", "loop", ext3_image_file, temp_rootfs_mount_dir] run_command(mount_command) copy_command = ["cp", "-a", f"{rootfs_dir}/.", temp_rootfs_mount_dir] run_command(copy_command) umount_command = ["umount", "-f", temp_rootfs_mount_dir] run_command(umount_command) output_dir = os.path.dirname(squashfs_output_file) os.makedirs(output_dir, exist_ok=True) mksquashfs_path = os.path.join(pep_host_dir, "usr", "bin", "mksquashfs") mksquashfs_command = [ mksquashfs_path, os.path.join(build_dir, "tmp"), squashfs_output_file, "-comp", "zstd", "-e19", ] logger.info(f"=> Executing mksquashfs command: {' '.join(mksquashfs_command)}") result = run_command(mksquashfs_command) if result.returncode != 0: logger.error(f"Error creating SquashFS image: {result.stderr.strip()}") return None chmod_command = ["chmod", "444", squashfs_output_file] run_command(chmod_command) return squashfs_output_file except Exception as e: logger.error(f"Unexpected error while creating SquashFS image: {e}") return None finally: # Cleanup temporary directories if os.path.exists(temp_rootfs_mount_dir): shutil.rmtree(temp_rootfs_mount_dir, ignore_errors=True) if os.path.exists(os.path.join(build_dir, "tmp")): shutil.rmtree(os.path.join(build_dir, "tmp"), ignore_errors=True) if os.path.exists(os.path.join(image_dir, "rootfs")): shutil.rmtree(os.path.join(image_dir, "rootfs"), ignore_errors=True)