1#!/usr/bin/env python3
2# -*- coding: utf-8 -*-
3#
4# === This file is part of Calamares - <https://calamares.io> ===
5#
6#   SPDX-FileCopyrightText: 2014 Aurélien Gâteau <agateau@kde.org>
7#   SPDX-FileCopyrightText: 2016 Anke Boersma <demm@kaosx.us>
8#   SPDX-FileCopyrightText: 2018 Adriaan de Groot <groot@kde.org>
9#   SPDX-License-Identifier: GPL-3.0-or-later
10#
11#   Calamares is Free Software: see the License-Identifier above.
12#
13
14import os
15import subprocess
16import shutil
17
18import libcalamares
19from libcalamares.utils import gettext_path, gettext_languages
20
21import gettext
22_translation = gettext.translation("calamares-python",
23                                   localedir=gettext_path(),
24                                   languages=gettext_languages(),
25                                   fallback=True)
26_ = _translation.gettext
27_n = _translation.ngettext
28
29
30def pretty_name():
31    return _( "Unmount file systems." )
32
33
34def list_mounts(root_mount_point):
35    """ List mount points.
36
37    :param root_mount_point:
38    :return:
39    """
40    lst = []
41
42    root_mount_point = os.path.normpath(root_mount_point)
43    for line in open("/etc/mtab").readlines():
44        device, mount_point, _ = line.split(" ", 2)
45
46        if os.path.commonprefix([root_mount_point, mount_point]) == root_mount_point:
47            lst.append((device, mount_point))
48
49    return lst
50
51
52def run():
53    """ Unmounts given mountpoints in decreasing order.
54
55    :return:
56    """
57    root_mount_point = libcalamares.globalstorage.value("rootMountPoint")
58
59    if(libcalamares.job.configuration and
60       "srcLog" in libcalamares.job.configuration and
61       "destLog" in libcalamares.job.configuration):
62        log_source = libcalamares.job.configuration["srcLog"]
63        log_destination = libcalamares.job.configuration["destLog"]
64        # Relocate log_destination into target system
65        log_destination = '{!s}/{!s}'.format(root_mount_point, log_destination)
66        # Make sure source is a string
67        log_source = '{!s}'.format(log_source)
68
69        # copy installation log before umount
70        if os.path.exists(log_source):
71            try:
72                shutil.copy2(log_source, log_destination)
73            except Exception as e:
74                libcalamares.utils.warning("Could not preserve file {!s}, "
75                                       "error {!s}".format(log_source, e))
76
77    if not root_mount_point:
78        return ("No mount point for root partition in globalstorage",
79                "globalstorage does not contain a \"rootMountPoint\" key, "
80                "doing nothing")
81
82    if not os.path.exists(root_mount_point):
83        return ("Bad mount point for root partition in globalstorage",
84                "globalstorage[\"rootMountPoint\"] is \"{}\", which does not "
85                "exist, doing nothing".format(root_mount_point))
86
87    lst = list_mounts(root_mount_point)
88    # Sort the list by mount point in decreasing order. This way we can be sure
89    # we unmount deeper dirs first.
90    lst.sort(key=lambda x: x[1], reverse=True)
91
92    for device, mount_point in lst:
93        # On success, no output; if the command fails, its output is
94        # in the exception object.
95        subprocess.check_output(["umount", "-lv", mount_point], stderr=subprocess.STDOUT)
96
97    os.rmdir(root_mount_point)
98
99    return None
100