Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
26 commits
Select commit Hold shift + click to select a range
d5a26f1
Convert patches between 32 and 64 bit library path
nephros Oct 11, 2021
5cd4d0d
fixup! Convert patches between 32 and 64 bit library path
nephros Oct 15, 2021
3b098ba
add some more clarity to variable names and things
nephros Oct 15, 2021
bf4bacb
fixup! add some more clarity to variable names and things
nephros Oct 15, 2021
d81a9b2
fixup! add some more clarity to variable names and things
nephros Oct 15, 2021
6e7aa42
Mangling for bitness the paths used in doPrepareCache
b100dian Oct 17, 2021
f6d2dc2
fixup! Mangling for bitness the paths used in doPrepareCache
nephros Oct 31, 2021
14d9c98
introduce config file for path manging candidates
nephros Oct 31, 2021
09c0c0d
use "convert" instead of "mangle" in script outout
nephros Oct 31, 2021
878feb6
fixup! use "convert" instead of "mangle" in script outout
nephros Oct 31, 2021
d7c6afc
MANGLE_CANDIDATES -> m_mangleCandidates, we are not a static string a…
nephros Oct 31, 2021
898d0fb
really wip
b100dian Oct 31, 2021
2dff6cb
fixup mangle candidates QStringList
b100dian Nov 1, 2021
98ad797
Merge branch 'master' into patch-bitness
nephros Nov 1, 2021
a7a52e0
correct dbus string array
b100dian Nov 1, 2021
48262fc
DISABLE_MANGLING with bitnessMangle + pm_unapply
b100dian Nov 1, 2021
ab04ee2
Use bitnessMangle flag in cpp too
b100dian Nov 1, 2021
18bcef5
Merge pull request #140 from b100dian/patch-bitness
nephros Nov 2, 2021
e88545e
add tools used in scripts to pkg requirements
nephros Nov 2, 2021
1b0c7e8
Merge remote-tracking branch 'upstream/master' into patch-bitness
nephros Nov 2, 2021
569eb58
Refresh patches on bitness mangling change
b100dian Nov 2, 2021
df88f45
mangle before test if applied seems to fix installtime + patch failure
b100dian Nov 2, 2021
d44efe6
show mangle paths always
nephros Nov 9, 2021
2c67753
align shown paths to indicator
nephros Nov 10, 2021
fdbb771
fixup! align shown paths to indicator
nephros Nov 10, 2021
b746ca5
remove test path
b100dian Nov 13, 2021
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
build/
*.pro.*
src/bin/patchmanager-daemon/adaptor.*
src/bin/patchmanager-daemon/patchmanager

*.rpm
*.so*
Expand Down
3 changes: 3 additions & 0 deletions rpm/patchmanager.spec
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,8 @@ URL: https://github.com/sailfishos-patches/patchmanager
Source0: %{name}-%{version}.tar.bz2
Requires: unzip
Requires: patch
Requires: grep
Requires: sed
Requires: sailfish-version >= 3.4.0
BuildRequires: pkgconfig(Qt5Core)
BuildRequires: pkgconfig(Qt5DBus)
Expand Down Expand Up @@ -168,6 +170,7 @@ systemctl-user daemon-reload
%{_userunitdir}/lipstick.service.wants/lipstick-patchmanager.service
%{_libdir}/libpreload%{name}.so
%{_sysconfdir}/firejail/whitelist-common-%{name}.local
%config(noreplace) %{_sysconfdir}/%{name}/manglelist.conf

%attr(0755,root,root) %{_libexecdir}/pm_apply
%attr(0755,root,root) %{_libexecdir}/pm_unapply
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,9 @@
<arg name="def" type="v" direction="in" />
<arg name="value" type="v" direction="out" />
</method>
<method name="getMangleCandidates">
<arg name="result" type="as" direction="out" />
</method>
<method name="checkEaster">
<arg name="easter" type="s" direction="out" />
</method>
Expand Down
Binary file added src/bin/patchmanager-daemon/patchmanager
Binary file not shown.
44 changes: 43 additions & 1 deletion src/bin/patchmanager-daemon/patchmanagerobject.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -86,7 +86,7 @@ static const QString PATCHES_WORK_DIR_PREFIX = QStringLiteral("/tmp/patchmanager
static const QString PATCHES_WORK_DIR = QStringLiteral("%1/%2").arg(PATCHES_WORK_DIR_PREFIX, "work");
static const QString PATCHES_ADDITIONAL_DIR = QStringLiteral("%1/%2").arg(PATCHES_WORK_DIR_PREFIX, "patches");
static const QString PATCH_FILE = QStringLiteral("patch.json");

static const QString MANGLE_CONFIG_FILE = QStringLiteral("/etc/patchmanager/manglelist.conf");
static const QString NAME_KEY = QStringLiteral("name");
static const QString DESCRIPTION_KEY = QStringLiteral("description");
static const QString CATEGORY_KEY = QStringLiteral("category");
Expand Down Expand Up @@ -288,6 +288,17 @@ void PatchManagerObject::setAppliedPatches(const QSet<QString> &patches)
putSettings(QStringLiteral("applied"), QStringList(patches.toList()));
}

QStringList PatchManagerObject::getMangleCandidates()
{
if (m_mangleCandidates.empty()) {
qDebug() << Q_FUNC_INFO;
auto mangleCandidates = QSettings(MANGLE_CONFIG_FILE, QSettings::IniFormat).value("MANGLE_CANDIDATES", "").toString();
m_mangleCandidates = mangleCandidates.split(' ', QString::SplitBehavior::SkipEmptyParts);
qDebug() << "Loaded mangle candidates:" << m_mangleCandidates;
}
return m_mangleCandidates;
}

void PatchManagerObject::getVersion()
{
qDebug() << Q_FUNC_INFO;
Expand Down Expand Up @@ -1157,6 +1168,10 @@ bool PatchManagerObject::putSettings(const QString &name, const QVariant &value)
QVariant old = m_settings->value(key);
if (old != value) {
m_settings->setValue(key ,value);
if (name == QStringLiteral("bitnessMangle")) {
qDebug() << Q_FUNC_INFO << "Changing bitness mangle refreshes patch list";
refreshPatchList();
}
return true;
}
return false;
Expand Down Expand Up @@ -1569,6 +1584,18 @@ void PatchManagerObject::doRefreshPatchList()
{
qDebug() << Q_FUNC_INFO;

// Create mangling replacement tokens.
QStringList toManglePaths{}, mangledPaths{};
if(getSettings(QStringLiteral("bitnessMangle"), false).toBool()) {
toManglePaths = getMangleCandidates();
mangledPaths = getMangleCandidates().replaceInStrings("/usr/lib/", "/usr/lib64/");
if (Q_PROCESSOR_WORDSIZE == 4) { // 32 bit
std::swap(toManglePaths, mangledPaths);
}
}
qDebug() << Q_FUNC_INFO << "toManglePaths" << toManglePaths;
qDebug() << Q_FUNC_INFO << "mangledPaths" << mangledPaths;

// load applied patches

m_appliedPatches = getAppliedPatches();
Expand All @@ -1590,6 +1617,14 @@ void PatchManagerObject::doRefreshPatchList()
if (line.startsWith(QByteArrayLiteral("+++ "))) {
const QString toPatch = QString::fromLatin1(line.split(' ')[1].split('\t')[0].split('\n')[0]);
QString path = toPatch;

for (int i = 0; i < toManglePaths.size(); i++) {
if (path.startsWith(toManglePaths[i])) {
qDebug() << Q_FUNC_INFO << "Editing path: " << path;
path.replace(toManglePaths[i], mangledPaths[i]);
}
}

while (!QFileInfo::exists(path) && path.count('/') > 1) {
path = path.mid(path.indexOf('/', 1));
}
Expand Down Expand Up @@ -1768,6 +1803,13 @@ bool PatchManagerObject::doPatch(const QString &patchName, bool apply, QString *
QStringList arguments;
arguments.append(patchName);

if (false == getSettings(QStringLiteral("bitnessMangle"), false).toBool()) {
QProcessEnvironment env = QProcessEnvironment::systemEnvironment();
qDebug() << Q_FUNC_INFO << "DISABLE_MANGLING=true";
env.insert("DISABLE_MANGLING", "true");
process.setProcessEnvironment(env);
}

process.setArguments(arguments);
qDebug() << Q_FUNC_INFO << "Starting:" << process.program() << process.arguments();
process.start();
Expand Down
5 changes: 5 additions & 0 deletions src/bin/patchmanager-daemon/patchmanagerobject.h
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,7 @@
#include <QtCore/QStringList>
#include <QtCore/QVariantMap>
#include <QtCore/QVariantList>
#include <QtCore/QVector>
#include <QtCore/QDir>

#include <QDBusConnection>
Expand Down Expand Up @@ -180,6 +181,8 @@ private slots:
void restartKeyboard();
void doRestartKeyboard();

QStringList getMangleCandidates();

private:
void restartService(const QString &serviceName);

Expand Down Expand Up @@ -237,6 +240,8 @@ private slots:

QString m_osRelease;

QStringList m_mangleCandidates;

PatchManagerAdaptor *m_adaptor = nullptr;
QNetworkAccessManager *m_nam = nullptr;

Expand Down
4 changes: 3 additions & 1 deletion src/etc/etc.pro
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
TEMPLATE = aux

manglelist.files = manglelist.conf
manglelist.path = /etc/patchmanager
firejail.files = whitelist-common-patchmanager.local
firejail.path = /etc/firejail
INSTALLS += firejail
INSTALLS += firejail manglelist

9 changes: 9 additions & 0 deletions src/etc/manglelist.conf
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
# Settings file for 32/64 bit path mangling
#
# must conform to both shell format, and be parseable as QSettings(foo, QSettings::IniFormat)

# list of candidate paths to attempt 32/64bit library path correction
# used by patchmanager-daemon and pm_apply.sh
# determined by a find /usr/lib -name "*.qml" and bug reports
# the list is given in "32bit" format, i.e. no lib64
MANGLE_CANDIDATES="/usr/lib/qt5/qml /usr/lib/jolla-mediaplayer /usr/lib/maliit/plugins"
22 changes: 22 additions & 0 deletions src/qml/SettingsPage.qml
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,28 @@ Page {
onClicked: PatchManager.developerMode = !PatchManager.developerMode
automaticCheck: false
}

TextSwitch {
id: fixBitSwitch
text: qsTranslate("", "Fix patches made for 32-bit or 64-bit only")
description: qsTranslate("", "Automatically fix lib or lib64 for select paths shown below.")
checked: PatchManager.bitnessMangle
onClicked: PatchManager.bitnessMangle = !PatchManager.bitnessMangle
automaticCheck: false
}

TextArea {
// align to the right of TextSwitch indicator
anchors {
left: fixBitSwitch.left
leftMargin: fixBitSwitch.leftMargin + Theme.paddingLarge
}
color: Theme.secondaryColor
font.pixelSize: Theme.fontSizeSmall
readOnly: true
text: PatchManager.mangleCandidates.join("\n")
enabled: fixBitSwitch.checked
}
}
}
}
22 changes: 22 additions & 0 deletions src/qml/patchmanager.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -197,13 +197,35 @@ bool PatchManager::applyOnBoot() const
return getSettingsSync(QStringLiteral("applyOnBoot"), false).toBool();
}

QStringList PatchManager::mangleCandidates() const
{
QDBusPendingReply<QStringList> reply = m_interface->getMangleCandidates();
reply.waitForFinished();
if (reply.isFinished()) {
qDebug() << Q_FUNC_INFO << "mangleCandidates() dbus replied:" << reply.value();
return reply.value();
}
return QStringList();
}

void PatchManager::setApplyOnBoot(bool applyOnBoot)
{
if (putSettingsSync(QStringLiteral("applyOnBoot"), applyOnBoot)) {
emit applyOnBootChanged(applyOnBoot);
}
}

bool PatchManager::bitnessMangle() const
{
return getSettingsSync(QStringLiteral("bitnessMangle"), false).toBool();
}

void PatchManager::setBitnessMangle(bool bitnessMangle)
{
if (putSettingsSync(QStringLiteral("bitnessMangle"), bitnessMangle)) {
emit bitnessMangleChanged(bitnessMangle);
}
}
PatchManagerModel *PatchManager::installedModel()
{
return m_installedModel;
Expand Down
6 changes: 6 additions & 0 deletions src/qml/patchmanager.h
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,8 @@ class PatchManager: public QObject
Q_PROPERTY(QString serverMediaUrl READ serverMediaUrl CONSTANT)
Q_PROPERTY(bool developerMode READ developerMode WRITE setDeveloperMode NOTIFY developerModeChanged)
Q_PROPERTY(bool applyOnBoot READ applyOnBoot WRITE setApplyOnBoot NOTIFY applyOnBootChanged)
Q_PROPERTY(bool bitnessMangle READ bitnessMangle WRITE setBitnessMangle NOTIFY bitnessMangleChanged)
Q_PROPERTY(QStringList mangleCandidates READ mangleCandidates)
Q_PROPERTY(PatchManagerModel *installedModel READ installedModel CONSTANT)
Q_PROPERTY(QVariantMap updates READ getUpdates NOTIFY updatesChanged)
Q_PROPERTY(QStringList updatesNames READ getUpdatesNames NOTIFY updatesChanged)
Expand All @@ -83,6 +85,9 @@ class PatchManager: public QObject
void setDeveloperMode(bool developerMode);
bool applyOnBoot() const;
void setApplyOnBoot(bool applyOnBoot);
bool bitnessMangle() const;
void setBitnessMangle(bool bitnessMangle);
QStringList mangleCandidates() const;
PatchManagerModel *installedModel();
QString trCategory(const QString &category) const;
QVariantMap getUpdates() const;
Expand Down Expand Up @@ -156,6 +161,7 @@ public slots:
void easterReceived(const QString & easterText);
void developerModeChanged(bool developerMode);
void applyOnBootChanged(bool applyOnBoot);
void bitnessMangleChanged(bool bitnessMangle);
void updatesChanged();
void toggleServicesChanged(bool toggleServices);
void failureChanged(bool failed);
Expand Down
79 changes: 79 additions & 0 deletions src/tools/pm_apply
Original file line number Diff line number Diff line change
Expand Up @@ -15,9 +15,18 @@ PM_LOG_FILE="$PM_VAR_DIR/patchmanager.log"
PM_PATCH_BACKUP_ROOT_DIR="$PM_VAR_DIR/patches"
PM_PATCH_BACKUP_DIR="$PM_PATCH_BACKUP_ROOT_DIR/$1"

SYS_BITNESS=$(/usr/bin/getconf LONG_BIT)

# Constants
PATCH_NAME="unified_diff.patch"
PATCH_PATH="$PATCH_DIR/$PATCH_NAME"
PATCH_EDITED_NAME="unified_diff_${SYS_BITNESS}bit.patch"

# list of candidate paths to attempt 32/64bit library path correction
MANGLE_CANDIDATES=""
if [ -z "$DISABLE_MANGLING" ] && [ -r "etc/patchmanager/manglelist.conf" ] ; then
source /etc/patchmanager/manglelist.conf
fi

ROOT_DIR="/tmp/patchmanager"

Expand All @@ -36,6 +45,11 @@ log() {
echo "$@" | tee -a "$PM_LOG_FILE"
}

log "Mangle candidates"
log $MANGLE_CANDIDATES
log "Disable mangling"
log $DISABLE_MANGLING

failure() {
log
log "*** FAILED ***"
Expand Down Expand Up @@ -68,6 +82,69 @@ test_if_applied() {
fi
}

# see issue #71: https://github.com/sailfishos-patches/patchmanager/issues/71
mangle_libpath() {
if [ -f "$PATCH_PATH" ]; then
log
log "----------------------------------"
[ $SYS_BITNESS -eq 32 ] && log "Checking paths for 32->64bit conversion"
[ $SYS_BITNESS -eq 64 ] && log "Checking paths for 64->32bit conversion"
log "----------------------------------"
log

found=0
candidates="$MANGLE_CANDIDATES"
if [ $SYS_BITNESS -eq 32 ]; then
# first, convert the candidate list
# variable expansion ${foo/lib/lib64} would work on bash, but not POSIX/ash/busybox
candidates=$(printf '%s' "$MANGLE_CANDIDATES" | sed 's@/usr/lib/@/usr/lib64/@g' )
fi

for p in $candidates; do
totl_lines=$(grep -c "^+++" "$PATCH_PATH")
cand_lines=$(grep -c "^+++ $p" "$PATCH_PATH")
if [ $cand_lines -eq 0 ]; then
continue # nothing found, try next
else
found=$(( $found + $cand_lines ))
if [ $totl_lines -ne $cand_lines ]; then
# if there are several references in the patch file our mangling might do too much and cause the patch to fail.
log "WARNING: mixed patch, conversion might not work"
fi
fi

patch_edited_path="$PM_PATCH_BACKUP_DIR"/"$PATCH_EDITED_NAME"
log "found: ${p}, replacing libpath references"

mkdir -p "$PM_PATCH_BACKUP_DIR"
# prepare the pattern
pr=""
if [ $SYS_BITNESS -eq 32 ]; then
pr=$(printf '%s' "$p" | sed 's@/usr/lib64/@/usr/lib/@')
elif [ $SYS_BITNESS -eq 64 ]; then
pr=$(printf '%s' "$p" | sed 's@/usr/lib/@/usr/lib64/@')
fi
# doit
printf '#\n# patch converted to %sbit library paths from original by Patchmanager 3.1\n# Date: %s\n#\n' $SYS_BITNESS $(date -Iseconds) > "$patch_edited_path"
sed "s@^+++ $p@+++ $pr@;s@^--- $p@--- $pr@" "$PATCH_PATH" >> "$patch_edited_path"
if [ $? -ne 0 ]; then
failure
fi
log
log "OK, conversion produced: $patch_edited_path"
log
# set the patch to apply to the new one:
PATCH_PATH="$patch_edited_path"
return
done
if [ $found -eq 0 ]; then
log
log "OK, found nothing to convert"
log
fi
fi
}

verify_text_patch() {
if [ -f "$PATCH_PATH" ]; then
log
Expand Down Expand Up @@ -157,6 +234,8 @@ fi
# The main function that controls all the magic stuff
#

mangle_libpath

test_if_applied

verify_text_patch
Expand Down
Loading