1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148
|
"""
Copyright (c) 2023 Proton AG
This file is part of Proton.
Proton is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
Proton is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with ProtonVPN. If not, see <https://www.gnu.org/licenses/>.
"""
from .metaclasses import Singleton
import os
import shutil
# Try to get the BaseDirectory module
try:
from xdg import BaseDirectory
except ImportError:
BaseDirectory = None
class ExecutionEnvironment(metaclass=Singleton):
PROTON_DIR_NAME = "Proton"
def __init__(self):
# If we run as a system user, use system paths
if os.getuid() == 0:
self._setup_as_system_user()
else:
# If we run as a normal user
self._setup_as_regular_user()
@property
def path_config(self):
self.generate_dirs(self._path_config)
return self._path_config
@property
def path_cache(self):
self.generate_dirs(self._path_cache)
return self._path_cache
@property
def path_logs(self):
self.generate_dirs(self._path_logs)
return self._path_logs
@property
def path_runtime(self):
self.generate_dirs(self._path_runtime)
return self._path_runtime
@property
def systemd_unit(self):
return self._path_systemd_unit
def generate_dirs(self, path):
if os.path.isdir(path):
return
os.makedirs(path, mode=0o700, exist_ok=True)
def _setup_as_system_user(self):
self._path_config = f'/etc/{self.PROTON_DIR_NAME}'
self._path_cache = f'/var/cache/{self.PROTON_DIR_NAME}'
self._path_logs = f'/var/log/{self.PROTON_DIR_NAME}'
self._path_runtime = f'/run/{self.PROTON_DIR_NAME}'
self._path_systemd_unit = '/etc/systemd/system'
def _setup_as_regular_user(self):
config_home, cache_home, runtime_dir = self._get_dir_paths()
self._path_config = os.path.join(config_home, self.PROTON_DIR_NAME)
self._path_cache = os.path.join(cache_home, self.PROTON_DIR_NAME)
self._path_logs = os.path.join(cache_home, self.PROTON_DIR_NAME, 'logs')
self._path_runtime = os.path.join(runtime_dir, self.PROTON_DIR_NAME)
self._path_systemd_unit = os.path.join(config_home, "systemd", "user")
def _get_dir_paths(self):
# If BaseDirectory is found then we can extract valuable data from it
if BaseDirectory:
config_home = BaseDirectory.xdg_config_home
cache_home = BaseDirectory.xdg_cache_home
runtime_dir = BaseDirectory.get_runtime_dir()
else:
# Otherwise use default constructed from $HOME environment variable
home = os.environ.get('HOME', None)
if home is None:
raise RuntimeError("Cannot figure out where to place files, is $HOME defined?")
config_home = os.path.join(home, '.config')
cache_home = os.path.join(home, '.cache')
runtime_dir = f'/run/user/{os.getuid()}'
return config_home, cache_home, runtime_dir
class ProductExecutionEnvironment(ExecutionEnvironment):
"""
This class serves the purpose of helping in standardizing folder structure
across products. Thus each product should derive from `ProductExecutionEnvironment`
and setting the class property `PRODUCT` to match its correspondent product.
This should help to more easily find files and improving cross-product
collaboration.
"""
PRODUCT = None
def __init__(self):
super().__init__()
if self.PRODUCT is None:
raise RuntimeError("`PRODUCT` is not set")
@property
def path_config(self):
path = os.path.join(super().path_config, self.PRODUCT)
self.generate_dirs(path)
return path
@property
def path_cache(self):
path = os.path.join(super().path_cache, self.PRODUCT)
self.generate_dirs(path)
return path
@property
def path_logs(self):
path = os.path.join(super().path_logs, self.PRODUCT)
self.generate_dirs(path)
return path
@property
def path_runtime(self):
path = os.path.join(super().path_runtime, self.PRODUCT)
self.generate_dirs(path)
return path
class VPNExecutionEnvironment(ProductExecutionEnvironment):
"""Execution environment dedicated for the VPN product."""
PRODUCT = "VPN"
|