diff --git a/exegol/model/ContainerConfig.py b/exegol/model/ContainerConfig.py index 8d16f8db..03bdd87a 100644 --- a/exegol/model/ContainerConfig.py +++ b/exegol/model/ContainerConfig.py @@ -24,7 +24,7 @@ from exegol.model.ExegolModules import ExegolModules from exegol.utils import FsUtils from exegol.utils.ExeLog import logger, ExeLog -from exegol.utils.FsUtils import check_sysctl_value +from exegol.utils.FsUtils import check_sysctl_value, mkdir from exegol.utils.GuiUtils import GuiUtils if EnvInfo.is_windows_shell or EnvInfo.is_mac_shell: @@ -1039,7 +1039,7 @@ def addVolume(self, else: # If the directory is created by exegol, bypass user preference and enable shared perms (if available) execute_update_fs = force_sticky_group or enable_sticky_group - path.mkdir(parents=True, exist_ok=True) + mkdir(path) except PermissionError: logger.error("Unable to create the volume folder on the filesystem locally.") logger.critical(f"Insufficient permissions to create the folder: {host_path}") diff --git a/exegol/utils/DataFileUtils.py b/exegol/utils/DataFileUtils.py index c5bd4031..7ab6a46a 100644 --- a/exegol/utils/DataFileUtils.py +++ b/exegol/utils/DataFileUtils.py @@ -1,4 +1,6 @@ import json +import os +import sys from json import JSONEncoder, JSONDecodeError from pathlib import Path from typing import Union, Dict, cast, Optional, Set, Any @@ -8,6 +10,7 @@ from exegol.config.ConstantConfig import ConstantConfig from exegol.utils.ExeLog import logger +from exegol.utils.FsUtils import mkdir, get_user_id class DataFileUtils: @@ -47,7 +50,7 @@ def __load_file(self): """ if not self._file_path.parent.is_dir(): logger.verbose(f"Creating config folder: {self._file_path.parent}") - self._file_path.parent.mkdir(parents=True, exist_ok=True) + mkdir(self._file_path.parent) if not self._file_path.is_file(): logger.verbose(f"Creating default file: {self._file_path}") self._create_config_file() @@ -72,6 +75,9 @@ def _create_config_file(self): try: with open(self._file_path, 'w') as file: file.write(self._build_file_content()) + if sys.platform == "linux" and os.getuid() == 0: + user_uid, user_gid = get_user_id() + os.chown(self._file_path, user_uid, user_gid) except PermissionError as e: logger.critical(f"Unable to open the file '{self._file_path}' ({e}). Please fix your file permissions or run exegol with the correct rights.") diff --git a/exegol/utils/FsUtils.py b/exegol/utils/FsUtils.py index 5d81f58e..1e781a70 100644 --- a/exegol/utils/FsUtils.py +++ b/exegol/utils/FsUtils.py @@ -1,9 +1,11 @@ import logging +import os import re import stat import subprocess +import sys from pathlib import Path, PurePath -from typing import Optional +from typing import Optional, Tuple from exegol.config.EnvInfo import EnvInfo from exegol.utils.ExeLog import logger @@ -104,3 +106,33 @@ def check_sysctl_value(sysctl: str, compare_to: str) -> bool: except PermissionError: logger.debug(f"Unable to read sysctl {sysctl} permission!") return False + + +def get_user_id() -> Tuple[int, int]: + user_uid_raw = os.getenv("SUDO_UID") + if user_uid_raw is None: + user_uid = os.getuid() + else: + user_uid = int(user_uid_raw) + user_gid_raw = os.getenv("SUDO_GID") + if user_gid_raw is None: + user_gid = os.getgid() + else: + user_gid = int(user_gid_raw) + return user_uid, user_gid + + +def mkdir(path): + try: + path.mkdir(parents=False, exist_ok=False) + if sys.platform == "linux" and os.getuid() == 0: + user_uid, user_gid = get_user_id() + os.chown(path, user_uid, user_gid) + except FileExistsError: + # The directory already exist, this setup can be skipped + pass + except FileNotFoundError: + # Create parent directory first + mkdir(path.parent) + # Then create the targeted directory + mkdir(path)