initial commit

This commit is contained in:
Kevin Muñoz 2024-10-13 11:11:58 -05:00
commit 3a783587af
Signed by: mrhacker
GPG Key ID: E5616555DD4EDAAE
36 changed files with 1496 additions and 0 deletions

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.8 KiB

View File

@ -0,0 +1,2 @@
SPDX-FileCopyrightText: 2020 Adriaan de Groot <groot@kde.org>
SPDX-License-Identifier: GPL-3.0-or-later

View File

@ -0,0 +1,239 @@
# SPDX-FileCopyrightText: no
# SPDX-License-Identifier: CC0-1.0
#
# Product branding information. This influences some global
# user-visible aspects of Calamares, such as the product
# name, window behavior, and the slideshow during installation.
#
# Additional styling can be done using the stylesheet.qss
# file, also in the branding directory.
---
componentName: default
### WELCOME / OVERALL WORDING
#
# These settings affect some overall phrasing and looks,
# which are most visible in the welcome page.
# This selects between different welcome texts. When false, uses
# the traditional "Welcome to the %1 installer.", and when true,
# uses "Welcome to the Calamares installer for %1." This allows
# to distinguish this installer from other installers for the
# same distribution.
welcomeStyleCalamares: false
# Should the welcome image (productWelcome, below) be scaled
# up beyond its natural size? If false, the image does not grow
# with the window but remains the same size throughout (this
# may have surprising effects on HiDPI monitors).
welcomeExpandingLogo: true
### WINDOW CONFIGURATION
#
# The settings here affect the placement of the Calamares
# window through hints to the window manager and initial
# sizing of the Calamares window.
# Size and expansion policy for Calamares.
# - "normal" or unset, expand as needed, use *windowSize*
# - "fullscreen", start as large as possible, ignore *windowSize*
# - "noexpand", don't expand automatically, use *windowSize*
windowExpanding: normal
# Size of Calamares window, expressed as w,h. Both w and h
# may be either pixels (suffix px) or font-units (suffix em).
# e.g. "800px,600px"
# "60em,480px"
# This setting is ignored if "fullscreen" is selected for
# *windowExpanding*, above. If not set, use constants defined
# in CalamaresUtilsGui, 800x520.
windowSize: 800px,520px
# Placement of Calamares window. Either "center" or "free".
# Whether "center" actually works does depend on the window
# manager in use (and only makes sense if you're not using
# *windowExpanding* set to "fullscreen").
windowPlacement: center
### PANELS CONFIGURATION
#
# Calamares has a main content area, and two panels (navigation
# and progress / sidebar). The panels can be controlled individually,
# or switched off. If both panels are switched off, the layout of
# the main content area loses its margins, on the assumption that
# you're doing something special.
# Kind of sidebar (panel on the left, showing progress).
# - "widget" or unset, use traditional sidebar (logo, items)
# - "none", hide it entirely
# - "qml", use calamares-sidebar.qml from branding folder
# In addition, you **may** specify a side, separated by a comma,
# from the kind. Valid sides are:
# - "left" (if not specified, uses this)
# - "right"
# - "top"
# - "bottom"
# For instance, "widget,right" is valid; so is "qml", which defaults
# to putting the sidebar on the left. Also valid is "qml,top".
# While "widget,top" is valid, the widgets code is **not** flexible
# and results will be terrible.
sidebar: widget
# Kind of navigation (button panel on the bottom).
# - "widget" or unset, use traditional navigation
# - "none", hide it entirely
# - "qml", use calamares-navigation.qml from branding folder
# In addition, you **may** specify a side, separated by a comma,
# from the kind. The same sides are valid as for *sidebar*,
# except the default is *bottom*.
navigation: widget
### STRINGS, IMAGES AND COLORS
#
# This section contains the "branding proper" of names
# and images, rather than global-look settings.
# These are strings shown to the user in the user interface.
# There is no provision for translating them -- since they
# are names, the string is included as-is.
#
# The four Url strings are the Urls used by the buttons in
# the welcome screen, and are not shown to the user. Clicking
# on the "Support" button, for instance, opens the link supportUrl.
# If a Url is empty, the corresponding button is not shown.
#
# bootloaderEntryName is how this installation / distro is named
# in the boot loader (e.g. in the GRUB menu).
#
# These strings support substitution from /etc/os-release
# if KDE Frameworks 5.58 are available at build-time. When
# enabled, ${varname} is replaced by the equivalent value
# from os-release. All the supported var-names are in all-caps,
# and are listed on the FreeDesktop.org site,
# https://www.freedesktop.org/software/systemd/man/os-release.html
# Note that ANSI_COLOR and CPE_NAME don't make sense here, and
# are not supported (the rest are). Remember to quote the string
# if it contains substitutions, or you'll get YAML exceptions.
#
# The *Url* entries are used on the welcome page, and they
# are visible as buttons there if the corresponding *show* keys
# are set to "true" (they can also be overridden).
strings:
productName: Condor Linux
#shortProductName: Generic
version: 2024.10.13
shortVersion: 2023.10.13
versionedName: Condor Linux "Uchiha"
#shortVersionedName: Condor Linux
bootloaderEntryName: Condor Linux
productUrl: https://condorcs.net/CondorLinux
supportUrl: https://condorcs.net/CondorLinux
knownIssuesUrl: https://condorcs.net/CondorLinux
releaseNotesUrl: https://condorcs.net/CondorLinux
#donateUrl:
# These images are loaded from the branding module directory.
#
# productBanner is an optional image, which if present, will be shown
# on the welcome page of the application, above the welcome text.
# It is intended to have a width much greater than height.
# It is displayed at 64px height (also on HiDPI).
# Recommended size is 64px tall, and up to 460px wide.
# productIcon is used as the window icon, and will (usually) be used
# by the window manager to represent the application. This image
# should be square, and may be displayed by the window manager
# as small as 16x16 (but possibly larger).
# productLogo is used as the logo at the top of the left-hand column
# which shows the steps to be taken. The image should be square,
# and is displayed at 80x80 pixels (also on HiDPI).
# productWallpaper is an optional image, which if present, will replace
# the normal solid background on every page of the application.
# It can be any size and proportion,
# and will be tiled to fit the entire window.
# For a non-tiled wallpaper, the size should be the same as
# the overall window, see *windowSize* above (800x520).
# productWelcome is shown on the welcome page of the application in
# the middle of the window, below the welcome text. It can be
# any size and proportion, and will be scaled to fit inside
# the window. Use `welcomeExpandingLogo` to make it non-scaled.
# Recommended size is 320x150.
#
# These filenames can also use substitutions from os-release (see above).
images:
# productBanner: "banner.png"
productIcon: "squid.png"
productLogo: "squid.png"
# productWallpaper: "wallpaper.png"
productWelcome: "languages.png"
# Colors for text and background components.
#
# - SidebarBackground is the background of the sidebar
# - SidebarText is the (foreground) text color
# - SidebarBackgroundCurrent sets the background of the current step.
# Optional, and defaults to the application palette.
# - SidebarTextCurrent is the text color of the current step.
#
# These colors can **also** be set through the stylesheet, if the
# branding component also ships a stylesheet.qss. Then they are
# the corresponding CSS attributes of #sidebarApp.
style:
SidebarBackground: "#292F34"
SidebarText: "#FFFFFF"
SidebarTextCurrent: "#292F34"
SidebarBackgroundCurrent: "#D35400"
### SLIDESHOW
#
# The slideshow is displayed during execution steps (e.g. when the
# installer is actually writing to disk and doing other slow things).
# The slideshow can be a QML file (recommended) which can display
# arbitrary things -- text, images, animations, or even play a game --
# during the execution step. The QML **is** abruptly stopped when the
# execution step is done, though, so maybe a game isn't a great idea.
#
# The slideshow can also be a sequence of images (not recommended unless
# you don't want QML at all in your Calamares). The images are displayed
# at a rate of 1 every 2 seconds during the execution step.
#
# To configure a QML file, list a single filename:
# slideshow: "show.qml"
# To configure images, like the filenames (here, as an inline list):
# slideshow: [ "/etc/calamares/slideshow/0.png", "/etc/logo.png" ]
slideshow: "show.qml"
# There are two available APIs for a QML slideshow:
# - 1 (the default) loads the entire slideshow when the installation-
# slideshow page is shown and starts the QML then. The QML
# is never stopped (after installation is done, times etc.
# continue to fire).
# - 2 loads the slideshow on startup and calls onActivate() and
# onLeave() in the root object. After the installation is done,
# the show is stopped (first by calling onLeave(), then destroying
# the QML components).
#
# An image slideshow does not need to have the API defined.
slideshowAPI: 2
# These options are to customize online uploading of logs to pastebins:
# - type : Defines the kind of pastebin service to be used. Currently
# it accepts two values:
# - none : disables the pastebin functionality
# - fiche : use fiche pastebin server
# - url : Defines the address of pastebin service to be used.
# Takes string as input. Important bits are the host and port,
# the scheme is not used.
# - sizeLimit : Defines maximum size limit (in KiB) of log file to be pasted.
# The option must be set, to have the log option work.
# Takes integer as input. If < 0, no limit will be forced,
# else only last (approximately) 'n' KiB of log file will be pasted.
# Please note that upload size may be slightly over the limit (due
# to last minute logging), so provide a suitable value.
uploadServer :
type : "fiche"
url : "http://termbin.com:9999"
sizeLimit : -1

View File

@ -0,0 +1,17 @@
<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE TS>
<TS version="2.1" language="ar">
<context>
<name>show</name>
<message>
<location filename="../show.qml" line="64"/>
<source>This is a second Slide element.</source>
<translation>عرض الثاني</translation>
</message>
<message>
<location filename="../show.qml" line="68"/>
<source>This is a third Slide element.</source>
<translation>عرض الثالث</translation>
</message>
</context>
</TS>

View File

@ -0,0 +1,17 @@
<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE TS>
<TS version="2.1" language="en">
<context>
<name>show</name>
<message>
<location filename="../show.qml" line="64"/>
<source>This is a second Slide element.</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../show.qml" line="68"/>
<source>This is a third Slide element.</source>
<translation type="unfinished"></translation>
</message>
</context>
</TS>

View File

@ -0,0 +1,17 @@
<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE TS>
<TS version="2.1" language="eo">
<context>
<name>show</name>
<message>
<location filename="../show.qml" line="64"/>
<source>This is a second Slide element.</source>
<translation>Ĉi tio estas la dua gliteja.</translation>
</message>
<message>
<location filename="../show.qml" line="68"/>
<source>This is a third Slide element.</source>
<translation>Ĉi tio estas la tria gliteja.</translation>
</message>
</context>
</TS>

View File

@ -0,0 +1,17 @@
<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE TS>
<TS version="2.1" language="fr">
<context>
<name>show</name>
<message>
<location filename="../show.qml" line="64"/>
<source>This is a second Slide element.</source>
<translation>Ceci est la deuxieme affiche.</translation>
</message>
<message>
<location filename="../show.qml" line="68"/>
<source>This is a third Slide element.</source>
<translation>La troisième affice ce trouve ici.</translation>
</message>
</context>
</TS>

View File

@ -0,0 +1,17 @@
<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE TS>
<TS version="2.1" language="nl">
<context>
<name>show</name>
<message>
<location filename="../show.qml" line="64"/>
<source>This is a second Slide element.</source>
<translation>Dit is het tweede Dia element.</translation>
</message>
<message>
<location filename="../show.qml" line="68"/>
<source>This is a third Slide element.</source>
<translation>Dit is het derde Dia element.</translation>
</message>
</context>
</TS>

Binary file not shown.

After

Width:  |  Height:  |  Size: 84 KiB

View File

@ -0,0 +1,2 @@
SPDX-FileCopyrightText: 2015 Teo Mrnjavac <teo@kde.org>
SPDX-License-Identifier: GPL-3.0-or-later

View File

@ -0,0 +1,77 @@
/* === This file is part of Calamares - <https://calamares.io> ===
*
* SPDX-FileCopyrightText: 2015 Teo Mrnjavac <teo@kde.org>
* SPDX-FileCopyrightText: 2018 Adriaan de Groot <groot@kde.org>
* SPDX-License-Identifier: GPL-3.0-or-later
*
* Calamares is Free Software: see the License-Identifier above.
*
*/
import QtQuick 2.0;
import calamares.slideshow 1.0;
Presentation
{
id: presentation
function nextSlide() {
console.log("QML Component (default slideshow) Next slide");
presentation.goToNextSlide();
}
Timer {
id: advanceTimer
interval: 1000
running: presentation.activatedInCalamares
repeat: true
onTriggered: nextSlide()
}
Slide {
Image {
id: background
source: "squid.png"
width: 200; height: 200
fillMode: Image.PreserveAspectFit
anchors.centerIn: parent
}
Text {
anchors.horizontalCenter: background.horizontalCenter
anchors.top: background.bottom
text: "This is a customizable QML slideshow.<br/>"+
"Distributions should provide their own slideshow and list it in <br/>"+
"their custom branding.desc file.<br/>"+
"To create a Calamares presentation in QML, import calamares.slideshow,<br/>"+
"define a Presentation element with as many Slide elements as needed."
wrapMode: Text.WordWrap
width: presentation.width
horizontalAlignment: Text.Center
}
}
Slide {
centeredText: qsTr("This is a second Slide element.")
}
Slide {
centeredText: qsTr("This is a third Slide element.")
}
// When this slideshow is loaded as a V1 slideshow, only
// activatedInCalamares is set, which starts the timer (see above).
//
// In V2, also the onActivate() and onLeave() methods are called.
// These example functions log a message (and re-start the slides
// from the first).
function onActivate() {
console.log("QML Component (default slideshow) activated");
presentation.currentSlide = 0;
}
function onLeave() {
console.log("QML Component (default slideshow) deactivated");
}
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 8.1 KiB

View File

@ -0,0 +1,2 @@
SPDX-FileCopyrightText: 2014 Teo Mrnjavac <teo@kde.org>
SPDX-License-Identifier: GPL-3.0-or-later

View File

@ -0,0 +1,96 @@
/*
* SPDX-FileCopyrightText: no
* SPDX-License-Identifier: CC0-1.0
*/
/*
A branding component can ship a stylesheet (like this one)
which is applied to parts of the Calamares user-interface.
In principle, all parts can be styled through CSS.
Missing parts should be filed as issues.
The IDs are based on the object names in the C++ code.
You can use the Debug Dialog to find out object names:
- Open the debug dialog
- Choose tab *Tools*
- Click *Widget Tree* button
The list of object names is printed in the log.
Documentation for styling Qt Widgets through a stylesheet
can be found at
https://doc.qt.io/qt-5/stylesheet-examples.html
https://doc.qt.io/qt-5/stylesheet-reference.html
In Calamares, styling widget classes is supported (e.g.
using `QComboBox` as a selector).
This example stylesheet has all the actual styling commented out.
The examples are not exhaustive.
*/
/*** Generic Widgets.
*
* You can style **all** widgets of a given class by selecting
* the class name. Some widgets have specialized sub-selectors.
*/
/*
QPushButton { background-color: green; }
*/
/*** Main application window.
*
* The main application window has the sidebar, which in turn
* contains a logo and a list of items -- note that the list
* can **not** be styled, since it has its own custom C++
* delegate code.
*/
/*
#mainApp { }
#sidebarApp { }
#logoApp { }
*/
/*** Welcome module.
*
* There are plenty of parts, but the buttons are the most interesting
* ones (donate, release notes, ...). The little icon image can be
* styled through *qproperty-icon*, which is a little obscure.
* URLs can reference the QRC paths of the Calamares application
* or loaded via plugins or within the filesystem. There is no
* comprehensive list of available icons, though.
*/
/*
QPushButton#aboutButton { qproperty-icon: url(:/data/images/release.svg); }
#donateButton,
#supportButton,
#releaseNotesButton,
#knownIssuesButton { qproperty-icon: url(:/data/images/help.svg); }
*/
/*** Partitioning module.
*
* Many moving parts, which you will need to experiment with.
*/
/*
#bootInfoIcon { }
#bootInfoLable { }
#deviceInfoIcon { }
#defineInfoLabel { }
#scrollAreaWidgetContents { }
#partitionBarView { }
*/
/*** Licensing module.
*
* The licensing module paints individual widgets for each of
* the licenses. The item can be collapsed or expanded.
*/
/*
#licenseItem { }
#licenseItemFullText { }
*/

View File

@ -0,0 +1,500 @@
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
#
# === This file is part of Calamares - <https://calamares.io> ===
#
# SPDX-FileCopyrightText: 2014 Teo Mrnjavac <teo@kde.org>
# SPDX-FileCopyrightText: 2014 Daniel Hillenbrand <codeworkx@bbqlinux.org>
# SPDX-FileCopyrightText: 2014 Philip Müller <philm@manjaro.org>
# SPDX-FileCopyrightText: 2017 Alf Gaida <agaida@siduction.org>
# SPDX-FileCopyrightText: 2019 Kevin Kofler <kevin.kofler@chello.at>
# SPDX-FileCopyrightText: 2020 Adriaan de Groot <groot@kde.org>
# SPDX-FileCopyrightText: 2020 Gabriel Craciunescu <crazy@frugalware.org>
# SPDX-License-Identifier: GPL-3.0-or-later
#
# Calamares is Free Software: see the License-Identifier above.
#
import os
import re
import shutil
import subprocess
import sys
import tempfile
import libcalamares
import gettext
_ = gettext.translation("calamares-python",
localedir=libcalamares.utils.gettext_path(),
languages=libcalamares.utils.gettext_languages(),
fallback=True).gettext
def pretty_name():
return _("Filling up filesystems.")
# This is going to be changed from various methods
status = pretty_name()
def pretty_status_message():
return status
class UnpackEntry:
"""
Extraction routine using rsync.
:param source:
:param sourcefs:
:param destination:
"""
__slots__ = ('source', 'sourcefs', 'destination', 'copied', 'total', 'exclude', 'excludeFile',
'mountPoint', 'weight')
def __init__(self, source, sourcefs, destination):
"""
@p source is the source file name (might be an image file, or
a directory, too)
@p sourcefs is a type indication; "file" is special, as is
"squashfs".
@p destination is where the files from the source go. This is
**already** prefixed by rootMountPoint, so should be a
valid absolute path within the host system.
The members copied and total are filled in by the copying process.
"""
self.source = source
self.sourcefs = sourcefs
self.destination = destination
self.exclude = None
self.excludeFile = None
self.copied = 0
self.total = 0
self.mountPoint = None
self.weight = 1
def is_file(self):
return self.sourcefs == "file"
def do_count(self):
"""
Counts the number of files this entry has.
"""
# Need a name we can use like a global
class counter(object):
count = 0
def cb_count(s):
counter.count += 1
if self.sourcefs == "squashfs":
libcalamares.utils.host_env_process_output(["unsquashfs", "-l", self.source], cb_count)
elif self.sourcefs == "ext4":
libcalamares.utils.host_env_process_output(["find", self.mountPoint, "-type", "f"], cb_count)
elif self.is_file():
# Hasn't been mounted, copy directly; find handles both
# files and directories.
libcalamares.utils.host_env_process_output(["find", self.source, "-type", "f"], cb_count)
self.total = counter.count
return self.total
def do_mount(self, base):
"""
Mount given @p entry as loop device underneath @p base
A *file* entry (e.g. one with *sourcefs* set to *file*)
is not mounted and just ignored.
:param base: directory to place all the mounts in.
:returns: None, but throws if the mount failed
"""
imgbasename = os.path.splitext(
os.path.basename(self.source))[0]
imgmountdir = os.path.join(base, imgbasename)
os.makedirs(imgmountdir, exist_ok=True)
# This is where it *would* go (files bail out before actually mounting)
self.mountPoint = imgmountdir
if self.is_file():
return
if os.path.isdir(self.source):
r = libcalamares.utils.mount(self.source, imgmountdir, "", "--bind")
elif os.path.isfile(self.source):
r = libcalamares.utils.mount(self.source, imgmountdir, self.sourcefs, "loop")
else: # self.source is a device
r = libcalamares.utils.mount(self.source, imgmountdir, self.sourcefs, "")
if r != 0:
libcalamares.utils.debug("Failed to mount '{}' (fs={}) (target={})".format(self.source, self.sourcefs, imgmountdir))
raise subprocess.CalledProcessError(r, "mount")
ON_POSIX = 'posix' in sys.builtin_module_names
def global_excludes():
"""
List excludes for rsync.
"""
lst = []
extra_mounts = libcalamares.globalstorage.value("extraMounts")
if extra_mounts is None:
extra_mounts = []
for extra_mount in extra_mounts:
mount_point = extra_mount["mountPoint"]
if mount_point:
lst.extend(['--exclude', mount_point + '/'])
return lst
def file_copy(source, entry, progress_cb):
"""
Extract given image using rsync.
:param source: Source file. This may be the place the entry's
image is mounted, or if it's a single file, the entry's source value.
:param entry: The UnpackEntry being copied.
:param progress_cb: A callback function for progress reporting.
Takes a number and a total-number.
"""
import time
dest = entry.destination
# `source` *must* end with '/' otherwise a directory named after the source
# will be created in `dest`: ie if `source` is "/foo/bar" and `dest` is
# "/dest", then files will be copied in "/dest/bar".
if not source.endswith("/") and not os.path.isfile(source):
source += "/"
num_files_total_local = 0
num_files_copied = 0 # Gets updated through rsync output
args = ['rsync', '-aHAXSr', '--filter=-x trusted.overlay.*']
args.extend(global_excludes())
if entry.excludeFile:
args.extend(["--exclude-from=" + entry.excludeFile])
if entry.exclude:
for f in entry.exclude:
args.extend(["--exclude", f])
args.extend(['--progress', source, dest])
# last_num_files_copied trails num_files_copied, and whenever at least 107 more
# files (file_count_chunk) have been copied, progress is reported and
# last_num_files_copied is updated. The chunk size isn't "tidy"
# so that all the digits of the progress-reported number change.
#
file_count_chunk = 107
class counter(object):
last_num_files_copied = 0
last_timestamp_reported = time.time()
last_total_reported = 0
def output_cb(line):
# rsync outputs progress in parentheses. Each line will have an
# xfer and a chk item (either ir-chk or to-chk) as follows:
#
# - xfer#x => Interpret it as 'file copy try no. x'
# - ir-chk=x/y, where:
# - x = number of files yet to be checked
# - y = currently calculated total number of files.
# - to-chk=x/y, which is similar and happens once the ir-chk
# phase (collecting total files) is over.
#
# If you're copying directory with some links in it, the xfer#
# might not be a reliable counter (for one increase of xfer, many
# files may be created).
m = re.findall(r'xfr#(\d+), ..-chk=(\d+)/(\d+)', line)
if m:
# we've got a percentage update
num_files_remaining = int(m[0][1])
num_files_total_local = int(m[0][2])
# adjusting the offset so that progressbar can be continuesly drawn
num_files_copied = num_files_total_local - num_files_remaining
now = time.time()
if (num_files_copied - counter.last_num_files_copied >= file_count_chunk) or (now - counter.last_timestamp_reported > 0.5):
counter.last_num_files_copied = num_files_copied
counter.last_timestamp_reported = now
counter.last_total_reported = num_files_total_local
progress_cb(num_files_copied, num_files_total_local)
try:
returncode = libcalamares.utils.host_env_process_output(args, output_cb)
except subprocess.CalledProcessError as e:
returncode = e.returncode
progress_cb(counter.last_num_files_copied, counter.last_total_reported) # Push towards 100%
# Mark this entry as really done
entry.copied = entry.total
# 23 is the return code rsync returns if it cannot write extended
# attributes (with -X) because the target file system does not support it,
# e.g., the FAT EFI system partition. We need -X because distributions
# using file system capabilities and/or SELinux require the extended
# attributes. But distributions using SELinux may also have SELinux labels
# set on files under /boot/efi, and rsync complains about those. The only
# clean way would be to split the rsync into one with -X and
# --exclude /boot/efi and a separate one without -X for /boot/efi, but only
# if /boot/efi is actually an EFI system partition. For now, this hack will
# have to do. See also:
# https://bugzilla.redhat.com/show_bug.cgi?id=868755#c50
# for the same issue in Anaconda, which uses a similar workaround.
if returncode != 0 and returncode != 23:
libcalamares.utils.warning("rsync failed with error code {}.".format(returncode))
return _("rsync failed with error code {}.").format(returncode)
return None
class UnpackOperation:
"""
Extraction routine using unsquashfs.
:param entries:
"""
def __init__(self, entries):
self.entries = entries
self.entry_for_source = dict((x.source, x) for x in self.entries)
self.total_weight = sum([e.weight for e in entries])
def report_progress(self):
"""
Pass progress to user interface
"""
progress = float(0)
current_total = 0
current_done = 0 # Files count in the current entry
complete_count = 0
complete_weight = 0 # This much weight already finished
for entry in self.entries:
if entry.total == 0:
# Total 0 hasn't counted yet
continue
if entry.total == entry.copied:
complete_weight += entry.weight
complete_count += 1
else:
# There is at most *one* entry in-progress
current_total = entry.total
current_done = entry.copied
complete_weight += entry.weight * ( 1.0 * current_done ) / current_total
break
if current_total > 0:
progress = ( 1.0 * complete_weight ) / self.total_weight
global status
status = _("Unpacking image {}/{}, file {}/{}").format((complete_count+1), len(self.entries), current_done, current_total)
libcalamares.job.setprogress(progress)
def run(self):
"""
Extract given image using unsquashfs.
:return:
"""
global status
source_mount_path = tempfile.mkdtemp()
try:
complete = 0
for entry in self.entries:
status = _("Starting to unpack {}").format(entry.source)
libcalamares.job.setprogress( ( 1.0 * complete ) / len(self.entries) )
entry.do_mount(source_mount_path)
entry.do_count() # Fill in the entry.total
self.report_progress()
error_msg = self.unpack_image(entry, entry.mountPoint)
if error_msg:
return (_("Failed to unpack image \"{}\"").format(entry.source),
error_msg)
complete += 1
return None
finally:
shutil.rmtree(source_mount_path, ignore_errors=True, onerror=None)
def unpack_image(self, entry, imgmountdir):
"""
Unpacks image.
:param entry:
:param imgmountdir:
:return:
"""
def progress_cb(copied, total):
""" Copies file to given destination target.
:param copied:
"""
entry.copied = copied
if total > entry.total:
entry.total = total
self.report_progress()
try:
if entry.is_file():
source = entry.source
else:
source = imgmountdir
return file_copy(source, entry, progress_cb)
finally:
if not entry.is_file():
subprocess.check_call(["umount", "-l", imgmountdir])
def get_supported_filesystems_kernel():
"""
Reads /proc/filesystems (the list of supported filesystems
for the current kernel) and returns a list of (names of)
those filesystems.
"""
PATH_PROCFS = '/proc/filesystems'
if os.path.isfile(PATH_PROCFS) and os.access(PATH_PROCFS, os.R_OK):
with open(PATH_PROCFS, 'r') as procfile:
filesystems = procfile.read()
filesystems = filesystems.replace(
"nodev", "").replace("\t", "").splitlines()
return filesystems
return []
def get_supported_filesystems():
"""
Returns a list of all the supported filesystems
(valid values for the *sourcefs* key in an item.
"""
return ["file"] + get_supported_filesystems_kernel()
def repair_root_permissions(root_mount_point):
"""
If the / of the system gets permission 777, change it down
to 755. Any other permission is left alone. This
works around standard behavior from squashfs where
permissions are (easily, accidentally) set to 777.
"""
existing_root_mode = os.stat(root_mount_point).st_mode & 0o777
if existing_root_mode == 0o777:
try:
os.chmod(root_mount_point, 0o755) # Want / to be rwxr-xr-x
except OSError as e:
libcalamares.utils.warning("Could not set / to safe permissions: {}".format(e))
# But ignore it
def extract_weight(entry):
"""
Given @p entry, a dict representing a single entry in
the *unpack* list, returns its weight (1, or whatever is
set if it is sensible).
"""
w = entry.get("weight", None)
if w:
try:
wi = int(w)
return wi if wi > 0 else 1
except ValueError:
libcalamares.utils.warning("*weight* setting {!r} is not valid.".format(w))
except TypeError:
libcalamares.utils.warning("*weight* setting {!r} must be number.".format(w))
return 1
def run():
"""
Unsquash filesystem.
"""
root_mount_point = libcalamares.globalstorage.value("rootMountPoint")
if not root_mount_point:
libcalamares.utils.warning("No mount point for root partition")
return (_("No mount point for root partition"),
_("globalstorage does not contain a \"rootMountPoint\" key."))
if not os.path.exists(root_mount_point):
libcalamares.utils.warning("Bad root mount point \"{}\"".format(root_mount_point))
return (_("Bad mount point for root partition"),
_("rootMountPoint is \"{}\", which does not exist.".format(root_mount_point)))
if libcalamares.job.configuration.get("unpack", None) is None:
libcalamares.utils.warning("No *unpack* key in job configuration.")
return (_("Bad unpackfs configuration"),
_("There is no configuration information."))
supported_filesystems = get_supported_filesystems()
# Bail out before we start when there are obvious problems
# - unsupported filesystems
# - non-existent sources
# - missing tools for specific FS
for entry in libcalamares.job.configuration["unpack"]:
source = os.path.abspath(entry["source"])
sourcefs = entry["sourcefs"]
if sourcefs not in supported_filesystems:
libcalamares.utils.warning("The filesystem for \"{}\" ({}) is not supported by your current kernel".format(source, sourcefs))
libcalamares.utils.warning(" ... modprobe {} may solve the problem".format(sourcefs))
return (_("Bad unpackfs configuration"),
_("The filesystem for \"{}\" ({}) is not supported by your current kernel").format(source, sourcefs))
if not os.path.exists(source):
libcalamares.utils.warning("The source filesystem \"{}\" does not exist".format(source))
return (_("Bad unpackfs configuration"),
_("The source filesystem \"{}\" does not exist").format(source))
if sourcefs == "squashfs":
if shutil.which("unsquashfs") is None:
libcalamares.utils.warning("Failed to find unsquashfs")
return (_("Bad unpackfs configuration"),
_("Failed to find unsquashfs, make sure you have the squashfs-tools package installed.") +
" " + _("Failed to unpack image \"{}\"").format(source))
unpack = list()
is_first = True
for entry in libcalamares.job.configuration["unpack"]:
source = os.path.abspath(entry["source"])
sourcefs = entry["sourcefs"]
destination = os.path.abspath(root_mount_point + entry["destination"])
if not os.path.isdir(destination) and sourcefs != "file":
libcalamares.utils.warning(("The destination \"{}\" in the target system is not a directory").format(destination))
if is_first:
return (_("Bad unpackfs configuration"),
_("The destination \"{}\" in the target system is not a directory").format(destination))
else:
libcalamares.utils.debug(".. assuming that the previous targets will create that directory.")
unpack.append(UnpackEntry(source, sourcefs, destination))
# Optional settings
if entry.get("exclude", None):
unpack[-1].exclude = entry["exclude"]
if entry.get("excludeFile", None):
unpack[-1].excludeFile = entry["excludeFile"]
unpack[-1].weight = extract_weight(entry)
is_first = False
repair_root_permissions(root_mount_point)
try:
unpackop = UnpackOperation(unpack)
return unpackop.run()
finally:
repair_root_permissions(root_mount_point)

View File

@ -0,0 +1,10 @@
# SPDX-FileCopyrightText: no
# SPDX-License-Identifier: CC0-1.0
# Syntax is YAML 1.2
---
type: "job"
name: "unpackfs"
interface: "python"
script: "main.py"
requiredModules: [ mount ]
weight: 12

View File

@ -0,0 +1,37 @@
#! /bin/sh
#
# SPDX-FileCopyrightText: 2019 Adriaan de Groot <groot@kde.org>
# SPDX-License-Identifier: BSD-2-Clause
#
# Test preparation for unpackfs; since there's a bunch
# of fiddly bits than need to be present for the tests,
# do that in a script rather than entirely in CTest.
#
SRCDIR=$( dirname "$0" )
# For test 3
mkdir /tmp/unpackfs-test-run-rootdir3
# For test 7
mkdir /tmp/unpackfs-test-run-rootdir3/realdest
# For test 9
mkdir /tmp/unpackfs-test-run-rootdir3/smalldest
if test 0 = $( id -u ) ; then
mount -t tmpfs -o size=32M tmpfs /tmp/unpackfs-test-run-rootdir3/smalldest
dd if=/dev/zero of=/tmp/unpackfs-test-run-rootdir3/smalldest/bogus.zero bs=1M count=1
fi
# Run tests
sh "$SRCDIR/../testpythonrun.sh" unpackfs
# Cleanup test 9
if test 0 = $( id -u ) ; then
umount /tmp/unpackfs-test-run-rootdir3/smalldest
fi
# Cleanup test 7
rm -rf /tmp/unpackfs-test-run-rootdir3/realdest
# Cleanup test 3
rmdir /tmp/unpackfs-test-run-rootdir3

View File

@ -0,0 +1,4 @@
# SPDX-FileCopyrightText: no
# SPDX-License-Identifier: CC0-1.0
---
bogus: true

View File

@ -0,0 +1,4 @@
# SPDX-FileCopyrightText: no
# SPDX-License-Identifier: CC0-1.0
---
rootMountPoint: /tmp/unpackfs-test-run-rootdir/

View File

@ -0,0 +1,4 @@
# SPDX-FileCopyrightText: no
# SPDX-License-Identifier: CC0-1.0
---
rootMountPoint: /tmp/unpackfs-test-run-rootdir3/

View File

@ -0,0 +1,4 @@
# SPDX-FileCopyrightText: no
# SPDX-License-Identifier: CC0-1.0
---
unpack: []

View File

@ -0,0 +1,4 @@
# SPDX-FileCopyrightText: no
# SPDX-License-Identifier: CC0-1.0
---
rootMountPoint: /tmp/unpackfs-test-run-rootdir3/

View File

@ -0,0 +1,10 @@
# SPDX-FileCopyrightText: no
# SPDX-License-Identifier: CC0-1.0
#
# Test that a "bogus" sourcefs (a filesystem kind that does not
# exist) fails gracefully.
---
unpack:
- source: .
sourcefs: bogus
destination: /

View File

@ -0,0 +1,4 @@
# SPDX-FileCopyrightText: no
# SPDX-License-Identifier: CC0-1.0
---
rootMountPoint: /tmp/unpackfs-test-run-rootdir3/

View File

@ -0,0 +1,7 @@
# SPDX-FileCopyrightText: no
# SPDX-License-Identifier: CC0-1.0
---
unpack:
- source: ./fakesource
sourcefs: ext4
destination: fakedest

View File

@ -0,0 +1,4 @@
# SPDX-FileCopyrightText: no
# SPDX-License-Identifier: CC0-1.0
---
rootMountPoint: /tmp/unpackfs-test-run-rootdir3/

View File

@ -0,0 +1,7 @@
# SPDX-FileCopyrightText: no
# SPDX-License-Identifier: CC0-1.0
---
unpack:
- source: .
sourcefs: ext4
destination: fakedest

View File

@ -0,0 +1,4 @@
# SPDX-FileCopyrightText: no
# SPDX-License-Identifier: CC0-1.0
---
rootMountPoint: /tmp/unpackfs-test-run-rootdir3/

View File

@ -0,0 +1,7 @@
# SPDX-FileCopyrightText: no
# SPDX-License-Identifier: CC0-1.0
---
unpack:
- source: .
sourcefs: ext4
destination: realdest

View File

@ -0,0 +1,6 @@
# SPDX-FileCopyrightText: no
# SPDX-License-Identifier: CC0-1.0
---
rootMountPoint: /tmp/unpackfs-test-run-rootdir/
localeConf:
- LANG: nl

View File

@ -0,0 +1,7 @@
# SPDX-FileCopyrightText: no
# SPDX-License-Identifier: CC0-1.0
---
unpack:
- source: .
sourcefs: ext4
destination: realdest

View File

@ -0,0 +1,5 @@
# SPDX-FileCopyrightText: no
# SPDX-License-Identifier: CC0-1.0
# This test uses a small destination FS, to make rsync fail
---
rootMountPoint: /tmp/unpackfs-test-run-rootdir3/

View File

@ -0,0 +1,8 @@
# SPDX-FileCopyrightText: no
# SPDX-License-Identifier: CC0-1.0
# This test uses a small destination FS, to make rsync fail
---
unpack:
- source: .
sourcefs: ext4
destination: smalldest

View File

@ -0,0 +1,100 @@
# SPDX-FileCopyrightText: no
# SPDX-License-Identifier: CC0-1.0
#
# Unsquash / unpack a filesystem. Multiple sources are supported, and
# they may be squashed or plain filesystems.
#
# Configuration:
#
# from globalstorage: rootMountPoint
# from job.configuration: the path to where to mount the source image(s)
# for copying an ordered list of unpack mappings for image file <->
# target dir relative to rootMountPoint.
---
# Each list item is unpacked, in order, to the target system.
#
# Each list item has the following **mandatory** attributes:
# - *source* path relative to the live / intstalling system to the image
# - *sourcefs* the type of the source files; valid entries are
# - `ext4` (copies the filesystem contents)
# - `squashfs` (unsquashes)
# - `file` (copies a file or directory)
# - (may be others if mount supports it)
# - *destination* path relative to rootMountPoint (so in the target
# system) where this filesystem is unpacked. It may be an
# empty string, which effectively is / (the root) of the target
# system.
#
# Each list item **optionally** can include the following attributes:
# - *exclude* is a list of values that is expanded into --exclude
# arguments for rsync (each entry in exclude gets its own --exclude).
# - *excludeFile* is a single file that is passed to rsync as an
# --exclude-file argument. This should be a full pathname
# inside the **host** filesystem.
# - *weight* is useful when the entries take wildly different
# times to unpack (e.g. with a squashfs, and one single file)
# and the total weight of this module should be distributed
# differently between the entries. (This is only relevant when
# there is more than one entry; by default all the entries
# have the same weight, 1)
#
# EXAMPLES
#
# Usually you list a filesystem image to unpack; you can use
# squashfs or an ext4 image. An empty destination is equivalent to "/",
# the root of the target system. The destination directory must exist
# in the target system.
#
# - source: "/path/to/filesystem.sqfs"
# sourcefs: "squashfs"
# destination: ""
#
# Multiple entries are unpacked in-order; if there is more than one
# item then only the first must exist beforehand -- it's ok to
# create directories with one unsquash and then to use those
# directories as a target from a second unsquash.
#
# - source: "/path/to/another/filesystem.img"
# sourcefs: "ext4"
# destination: ""
# - source: "/path/to/another/filesystem2.img"
# sourcefs: "ext4"
# destination: "/usr/lib/extra"
#
# You can list filesystem source paths relative to the Calamares run
# directory, if you use -d (this is only useful for testing, though).
#
# - source: ./example.sqfs
# sourcefs: squashfs
# destination: ""
#
# You can list individual files (copied one-by-one), or directories
# (the files inside this directory are copied directly to the destination,
# so no "dummycpp/" subdirectory is created in this example).
# Do note that the target directory must exist already (e.g. from
# extracting some other filesystem).
#
# - source: ../CHANGES
# sourcefs: file
# destination: "/tmp/derp"
# - source: ../src/modules/dummycpp
# sourcefs: file
# destination: "/tmp/derp"
#
# The *destination* and *source* are handed off to rsync, so the semantics
# of trailing slashes apply. In order to *rename* a file as it is
# copied, specify one single file (e.g. CHANGES) and a full pathname
# for its destination name, as in the example below.
unpack:
- source: ../CHANGES
sourcefs: file
destination: "/tmp/changes.txt"
weight: 1 # Single file
- source: src/qml/calamares/slideshow
sourcefs: file
destination: "/tmp/slideshow/"
exclude: [ "*.qmlc", "qmldir" ]
weight: 5 # Lots of files
# excludeFile: /etc/calamares/modules/unpackfs/exclude-list.txt

View File

@ -0,0 +1,21 @@
# SPDX-FileCopyrightText: 2020 Adriaan de Groot <groot@kde.org>
# SPDX-License-Identifier: GPL-3.0-or-later
---
$schema: https://json-schema.org/schema#
$id: https://calamares.io/schemas/unpackfs
additionalProperties: false
type: object
properties:
unpack:
type: array
items:
type: object
additionalProperties: false
properties:
source: { type: string }
sourcefs: { type: string }
destination: { type: string }
excludeFile: { type: string }
exclude: { type: array, items: { type: string } }
weight: { type: integer, exclusiveMinimum: 0 }
required: [ source , sourcefs, destination ]

236
etc/calamares/settings.conf Normal file
View File

@ -0,0 +1,236 @@
# SPDX-FileCopyrightText: no
# SPDX-License-Identifier: CC0-1.0
#
# Configuration file for Calamares
#
# This is the top-level configuration file for Calamares.
# It specifies what modules will be used, as well as some
# overall characteristics -- is this a setup program, or
# an installer. More specific configuration is devolved
# to the branding file (for the UI) and the individual
# module configuration files (for functionality).
---
# Modules can be job modules (with different interfaces) and QtWidgets view
# modules. They could all be placed in a number of different paths.
# "modules-search" is a list of strings, each of these can either be a full
# path to a directory or the keyword "local".
#
# "local" means:
# - modules in $LIBDIR/calamares/modules, with
# - settings in SHARE/calamares/modules or /etc/calamares/modules.
# In debug-mode (e.g. calamares -d) "local" also adds some paths
# that make sense from inside the build-directory, so that you
# can build-and-run with the latest modules immediately.
#
# Strings other than "local" are taken as paths and interpreted
# relative to wherever Calamares is started. It is therefore **strongly**
# recommended to use only absolute paths here. This is mostly useful
# if your distro has forks of standard Calamares modules, but also
# uses some form of upstream packaging which might overwrite those
# forked modules -- then you can keep modules somewhere outside of
# the "regular" module tree.
#
#
# YAML: list of strings.
modules-search: [ local ]
# Instances section. This section is optional, and it defines custom instances
# for modules of any kind. An instance entry has these keys:
# - *module* name, which matches the module name from the module descriptor
# (usually the name of the directory under `src/modules/`, but third-
# party modules may diverge.
# - *id* (optional) an identifier to distinguish this instance from
# all the others. If none is given, the name of the module is used.
# Together, the module and id form an instance key (see below).
# - *config* (optional) a filename for the configuration. If none is
# given, *module*`.conf` is used (e.g. `welcome.conf` for the welcome
# module)
# - *weight* (optional) In the *exec* phase of the sequence, progress
# is reported as jobs are completed. The jobs from a single module
# together contribute the full weight of that module. The overall
# progress (0 .. 100%) is divided up according to the weight of each
# module. Give modules that take a lot of time to complete, a larger
# weight to keep the overall progress moving along steadily. This
# weight overrides a weight given in the module descriptor. If no weight
# is given, uses the value from the module descriptor, or 1 if there
# isn't one there either.
#
# The primary goal of this mechanism is to allow loading multiple instances
# of the same module, with different configuration. If you don't need this,
# the instances section can safely be left empty.
#
# Module name plus instance name makes an instance key, e.g.
# "packagechooserq@licenseq", where "packagechooserq" is the module name (for the packagechooserq
# viewmodule) and "licenseq" is the instance name. In the *sequence*
# section below, use instance-keys to name instances (instead of just
# a module name, for modules which have only a single instance).
#
# Every module implicitly has an instance with the instance name equal
# to its module name, e.g. "welcome@welcome". In the *sequence* section,
# mentioning a module without a full instance key (e.g. "welcome")
# means that implicit module.
#
# An instance may specify its configuration file (e.g. `webview-home.conf`).
# The implicit instances all have configuration files named `<module>.conf`.
# This (implict) way matches the source examples, where the welcome
# module contains an example `welcome.conf`. Specify a *config* for
# any module (also implicit instances) to change which file is used.
#
# For more information on running module instances, run Calamares in debug
# mode and check the Modules page in the Debug information interface.
#
# A module that is often used with instances is shellprocess, which will
# run shell commands specified in the configuration file. By configuring
# more than one instance of the module, multiple shell sessions can be run
# during install.
#
# YAML: list of maps of string:string key-value pairs.
#instances:
#- id: licenseq
# module: packagechooserq
# config: licenseq.conf
# Sequence section. This section describes the sequence of modules, both
# viewmodules and jobmodules, as they should appear and/or run.
#
# A jobmodule instance key (or name) can only appear in an exec phase, whereas
# a viewmodule instance key (or name) can appear in both exec and show phases.
# There is no limit to the number of show or exec phases. However, the same
# module instance key should not appear more than once per phase, and
# deployers should take notice that the global storage structure is persistent
# throughout the application lifetime, possibly influencing behavior across
# phases. A show phase defines a sequence of viewmodules (and therefore
# pages). These viewmodules can offer up jobs for the execution queue.
#
# An exec phase displays a progress page (with brandable slideshow). This
# progress page iterates over the modules listed in the *immediately
# preceding* show phase, and enqueues their jobs, as well as any other jobs
# from jobmodules, in the order defined in the current exec phase.
#
# It then executes the job queue and clears it. If a viewmodule offers up a
# job for execution, but the module name (or instance key) isn't listed in the
# immediately following exec phase, this job will not be executed.
#
# YAML: list of lists of strings.
sequence:
- show:
- welcome
# - notesqml
# - packagechooserq@licenseq
- locale
- keyboard
- partition
- users
# - tracking
- summary
- exec:
# - dummycpp
# - dummyprocess
# - dummypython
- partition
# - zfs
- mount
- unpackfs
- machineid
- locale
- keyboard
- localecfg
# - luksbootkeyfile
# - luksopenswaphookcfg
# - dracutlukscfg
- fstab
# - plymouthcfg
# - zfshostid
- initcpiocfg
- initcpio
- users
- displaymanager
- networkcfg
- hwclock
- services-systemd
# - dracut
- initramfs
# - grubcfg
- bootloader
- umount
- show:
- finished
# A branding component is a directory, either in SHARE/calamares/branding or
# in /etc/calamares/branding (the latter takes precedence). The directory must
# contain a YAML file branding.desc which may reference additional resources
# (such as images) as paths relative to the current directory.
#
# A branding component can also ship a QML slideshow for execution pages,
# along with translation files.
#
# Only the name of the branding component (directory) should be specified
# here, Calamares then takes care of finding it and loading the contents.
#
# YAML: string.
branding: default
# If this is set to true, Calamares will show an "Are you sure?" prompt right
# before each execution phase, i.e. at points of no return. If this is set to
# false, no prompt is shown. Default is false, but Calamares will complain if
# this is not explicitly set.
#
# YAML: boolean.
prompt-install: false
# If this is set to true, Calamares will execute all target environment
# commands in the current environment, without chroot. This setting should
# only be used when setting up Calamares as a post-install configuration tool,
# as opposed to a full operating system installer.
#
# Some official Calamares modules are not expected to function with this
# setting. (e.g. partitioning seems like a bad idea, since that is expected to
# have been done already)
#
# Default is false (for a normal installer), but Calamares will complain if
# this is not explicitly set.
#
# YAML: boolean.
dont-chroot: false
# If this is set to true, Calamares refers to itself as a "setup program"
# rather than an "installer". Defaults to the value of dont-chroot, but
# Calamares will complain if this is not explicitly set.
oem-setup: false
# If this is set to true, the "Cancel" button will be disabled entirely.
# The button is also hidden from view.
#
# This can be useful if when e.g. Calamares is used as a post-install
# configuration tool and you require the user to go through all the
# configuration steps.
#
# Default is false, but Calamares will complain if this is not explicitly set.
#
# YAML: boolean.
disable-cancel: false
# If this is set to true, the "Cancel" button will be disabled once
# you start the 'Installation', meaning there won't be a way to cancel
# the Installation until it has finished or installation has failed.
#
# Default is false, but Calamares will complain if this is not explicitly set.
#
# YAML: boolean.
disable-cancel-during-exec: false
# If this is set to true, the "Next" and "Back" button will be hidden once
# you start the 'Installation'.
#
# Default is false, but Calamares will complain if this is not explicitly set.
#
# YAML: boolean.
hide-back-and-next-during-exec: false
# If this is set to true, then once the end of the sequence has
# been reached, the quit (done) button is clicked automatically
# and Calamares will close. Default is false: the user will see
# that the end of installation has been reached, and that things are ok.
#
#
quit-at-end: false