diff --git a/src/application.cpp b/src/application.cpp index 004aa5646c0e2f62d1bfc3257c851482cbe1a9ea..bebd3fd559d5cc9ccf4e8967e0d8fef962aa9107 100644 --- a/src/application.cpp +++ b/src/application.cpp @@ -27,6 +27,15 @@ Application::Application(int &argc, char **argv) { } +void Application::dappWatch() +{ + m_watcher = new QFileSystemWatcher(this); + m_watcher->addPath("/opt/apps"); + connect(m_watcher,&QFileSystemWatcher::directoryChanged,this,[=](const QString &path){ + m_dstoreTool->run(); + }); +} + int Application::run() { // if (!QDBusConnection::systemBus().registerService("com.yoyo.Daemon")) { @@ -37,6 +46,8 @@ int Application::run() // qDebug() << QDBusConnection::systemBus().registerService("com.yoyo.Daemon") << " registerService"; m_appManager = new AppManager(this); + m_dstoreTool = new DStoreTool(this); + dappWatch(); return QCoreApplication::exec(); } diff --git a/src/application.h b/src/application.h index 5e6adf85c86de14e6e0d0bf283eed69bf443182d..0bdf61796a6e4cf6a4b70f444fb7e23855511fe3 100644 --- a/src/application.h +++ b/src/application.h @@ -21,7 +21,9 @@ #define APPLICATION_H #include +#include #include "appmanager.h" +#include "dstoretool.h" class Application : public QCoreApplication { @@ -31,9 +33,12 @@ public: explicit Application(int &argc, char **argv); int run(); + void dappWatch(); private: + QFileSystemWatcher * m_watcher; AppManager *m_appManager; + DStoreTool *m_dstoreTool; }; diff --git a/src/dstoretool.cpp b/src/dstoretool.cpp new file mode 100644 index 0000000000000000000000000000000000000000..f5e81d9dc59f460d44e85f52f6f7baa683a3d7fb --- /dev/null +++ b/src/dstoretool.cpp @@ -0,0 +1,184 @@ +#include "dstoretool.h" + +DStoreTool::DStoreTool(QObject *parent) + : QObject(parent) +{ + run(); +} + +void DStoreTool::run() +{ + cleanLink(); + for (auto &a : enumAppInfoList()) { + linkApp(a); + } + update(); +} + +QList DStoreTool::enumAppInfoList() +{ + QList appInfoList; + QDir apps("/opt/apps"); + auto list = apps.entryList(QDir::Dirs | QDir::NoDotAndDotDot); + for (auto &appID : list) { + auto infoPath = apps.absoluteFilePath(appID + "/info"); + QFile infoFile(infoPath); + if (!infoFile.open(QIODevice::ReadOnly)) { + continue; + } + auto doc = QJsonDocument::fromJson(infoFile.readAll()); + appInfoList.push_back(doc.object()); + } + return appInfoList; +} + +//这段是去找appid和info,没看懂用来干啥的,在此之后info文件也没再用过 +//可能以后版本的实现会用到,等官方加功能再说 +void DStoreTool::linkDir(const QString &source, const QString &target) +{ + auto ensureTargetDir = [](const QString &targetFile) { + QFileInfo t(targetFile); + QDir tDir(t.dir()); + tDir.mkpath("."); + }; + + QDir sourceDir(source); + QDir targetDir(target); + QDirIterator iter(source, QDir::Files | QDir::NoDotAndDotDot, QDirIterator::Subdirectories); + while (iter.hasNext()) { + auto sourceFile = iter.next(); + auto targetFile = targetDir.absoluteFilePath(sourceDir.relativeFilePath(sourceFile)); + + QFileInfo tfi(targetFile); + // if (tfi.isSymLink() && (tfi.canonicalFilePath() == sourceFile)) { + //这里官方应该是写错了,否则会每触发一次就把所有软链接都删了重新创建一次 + if (tfi.isSymLink() && (tfi.symLinkTarget() == sourceFile)) { + continue; + } else { + QFile::remove(targetFile); + } + + ensureTargetDir(targetFile); + auto ret = symlink(sourceFile.toStdString().c_str(), targetFile.toStdString().c_str()); + if (0 != ret) { + qDebug() << "link failed" << sourceFile << "=>" << targetFile << ret; + } + } +} + +//reset Dynamic library rpath +void DStoreTool:setRpath(const QString &file, const QString &path) +{ + if (!QFileInfo::exists(path)) + return; + QProcess p; + auto cmd = "patchelf " + file + " --set-rpath " + path; + p.start("bash", QStringList {"-c", cmd}); + p.waitForFinished(); +} + +QString DStoreTool:getGlic() +{ + //get arch & glibc + QProcess p; + auto cmd = "gcc -dumpmachine"; + p.start("bash", QStringList {"-c", cmd}); + p.waitForFinished(); + return p.readAll(); +} + +void DStoreTool:linkApp(const QJsonObject &app) +{ + auto appID = app.value("appid").toString(); + auto appEntriesDir = QDir("/opt/apps/" + appID + "/entries"); + auto appLibsDir = QDir("/opt/apps/" + appID + "/files/lib"); + auto autoStartDir = QDir(appEntriesDir.absoluteFilePath("autostart")); + + bool autoStart = app.value("permissions").toObject().value("autostart").toBool(); + if (autoStart) { + linkDir(appEntriesDir.absoluteFilePath("autostart"), "/etc/xdg/autostart"); + } + + // link application + auto sysShareDir = QDir("/usr/share"); + linkDir(appEntriesDir.absoluteFilePath("applications"), sysShareDir.absoluteFilePath("applications")); + linkDir(appEntriesDir.absoluteFilePath("icons"), sysShareDir.absoluteFilePath("icons")); + linkDir(appEntriesDir.absoluteFilePath("mime"), sysShareDir.absoluteFilePath("mime")); + linkDir(appEntriesDir.absoluteFilePath("glib-2.0"), sysShareDir.absoluteFilePath("glib-2.0")); + linkDir(appEntriesDir.absoluteFilePath("services"), sysShareDir.absoluteFilePath("dbus-1/services")); + linkDir(appEntriesDir.absoluteFilePath("GConf"), sysShareDir.absoluteFilePath("GConf")); + linkDir(appEntriesDir.absoluteFilePath("help"), sysShareDir.absoluteFilePath("help")); + linkDir(appEntriesDir.absoluteFilePath("locale"), sysShareDir.absoluteFilePath("locale")); + linkDir(appEntriesDir.absoluteFilePath("fcitx"), sysShareDir.absoluteFilePath("fcitx")); + linkDir(appEntriesDir.absoluteFilePath("polkit"), sysShareDir.absoluteFilePath("polkit-1")); + linkDir(appEntriesDir.absoluteFilePath("fonts/conf"), "/etc/fonts/conf.d"); + linkDir(appEntriesDir.absoluteFilePath("fonts/files"), sysShareDir.absoluteFilePath("fonts")); + + +//原来会导致Gtk相关应用翻译缺失,补足了 + + + auto pluginDir = QDir(appEntriesDir.absoluteFilePath("plugins")); + if (pluginDir.exists()) { + QString arch = getGlic(); + // if (pluginDir.exists()) { + // QDirIterator iter(pluginDir.absolutePath(), QDir::Files | QDir::NoDotAndDotDot, QDirIterator::Subdirectories); + // while (iter.hasNext()) { + // auto sourceFile = iter.next(); + // setRpath(sourceFile, appLibsDir.absolutePath()); //set rpath + // } + // } + + linkDir(appEntriesDir.absoluteFilePath("plugins/fcitx"), "/usr/lib/" + arch + "/fcitx"); + linkDir(appEntriesDir.absoluteFilePath("plugins/browser"), "/usr/lib/mozilla/plugins"); + } +} + +void DStoreTool:cleanLink() +{ + auto cleanDirBrokenLink = [](const QString &dir) { + QProcess p; + auto cmd = "find " + dir + " -xtype l -delete"; + p.start("bash", QStringList {"-c", cmd}); + p.waitForFinished(); + }; + + QString arch = getGlic(); + auto sysShareDir = QDir("/usr/share"); + cleanDirBrokenLink(sysShareDir.absoluteFilePath("applications")); + cleanDirBrokenLink(sysShareDir.absoluteFilePath("icons")); + cleanDirBrokenLink(sysShareDir.absoluteFilePath("mime/packages")); + cleanDirBrokenLink(sysShareDir.absoluteFilePath("glib-2.0")); + cleanDirBrokenLink(sysShareDir.absoluteFilePath("dbus-1/services")); + cleanDirBrokenLink("/etc/xdg/autostart"); + cleanDirBrokenLink(sysShareDir.absoluteFilePath("fcitx")); + cleanDirBrokenLink(sysShareDir.absoluteFilePath("help")); + cleanDirBrokenLink(sysShareDir.absoluteFilePath("locale")); + cleanDirBrokenLink("/usr/lib/" + arch + "/fcitx"); + cleanDirBrokenLink("/usr/lib/mozilla/plugins"); + cleanDirBrokenLink(sysShareDir.absoluteFilePath("polkit-1/actions")); + cleanDirBrokenLink(sysShareDir.absoluteFilePath("fonts")); + cleanDirBrokenLink("/etc/fonts/conf.d"); +} + +void DStoreTool:update() +{ + QProcess p; + auto cmd = "glib-compile-schemas /usr/share/glib-2.0/schemas/"; + p.start("bash", QStringList {"-c", cmd}); + p.waitForFinished(); + + cmd = "update-icon-caches /usr/share/icons/*"; + p.start("bash", QStringList {"-c", cmd}); + p.waitForFinished(); + + cmd = "update-desktop-database -q"; + p.start("bash", QStringList {"-c", cmd}); + p.waitForFinished(); + + cmd = "update-mime-database -V /usr/share/mime"; + p.start("bash", QStringList {"-c", cmd}); + p.waitForFinished(); + + +} \ No newline at end of file diff --git a/src/dstoretool.h b/src/dstoretool.h new file mode 100644 index 0000000000000000000000000000000000000000..ae76a906eeac7661cd617b65e62b156b5771bcc1 --- /dev/null +++ b/src/dstoretool.h @@ -0,0 +1,34 @@ +#ifndef DSTORETOOL_H +#define DSTORETOOL_H + +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +class DStoreTool : public QObject +{ + Q_OBJECT + +public: + void run(); + +private: + QList enumAppInfoList() + void linkDir(const QString &source, const QString &target) + void setRpath(const QString &file, const QString &path) + QString getGlic() + void linkApp(const QJsonObject &app) + void cleanLink() + void update() +private: + +}; + +#endif // DSTORETOOL_H