mirror of
https://github.com/AyuGram/AyuGramDesktop.git
synced 2025-06-05 06:33:57 +02:00
Add support for write-protected update on Linux
This commit is contained in:
parent
4fae827f1e
commit
578833446d
3 changed files with 79 additions and 13 deletions
|
@ -8,6 +8,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
||||||
#include <cstdio>
|
#include <cstdio>
|
||||||
#include <sys/stat.h>
|
#include <sys/stat.h>
|
||||||
#include <sys/types.h>
|
#include <sys/types.h>
|
||||||
|
#include <sys/wait.h>
|
||||||
#include <sys/sendfile.h>
|
#include <sys/sendfile.h>
|
||||||
#include <cstdlib>
|
#include <cstdlib>
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
|
@ -88,7 +89,7 @@ void writeLog(const char *format, ...) {
|
||||||
va_end(args);
|
va_end(args);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool copyFile(const char *from, const char *to) {
|
bool copyFile(const char *from, const char *to, bool writeprotected) {
|
||||||
FILE *ffrom = fopen(from, "rb"), *fto = fopen(to, "wb");
|
FILE *ffrom = fopen(from, "rb"), *fto = fopen(to, "wb");
|
||||||
if (!ffrom) {
|
if (!ffrom) {
|
||||||
if (fto) fclose(fto);
|
if (fto) fclose(fto);
|
||||||
|
@ -134,7 +135,7 @@ bool copyFile(const char *from, const char *to) {
|
||||||
}
|
}
|
||||||
|
|
||||||
//update to the same uid/gid
|
//update to the same uid/gid
|
||||||
if (fchown(fileno(fto), fst.st_uid, fst.st_gid) != 0) {
|
if (!writeprotected && fchown(fileno(fto), fst.st_uid, fst.st_gid) != 0) {
|
||||||
fclose(ffrom);
|
fclose(ffrom);
|
||||||
fclose(fto);
|
fclose(fto);
|
||||||
return false;
|
return false;
|
||||||
|
@ -233,7 +234,7 @@ void delFolder() {
|
||||||
rmdir(delFolder.c_str());
|
rmdir(delFolder.c_str());
|
||||||
}
|
}
|
||||||
|
|
||||||
bool update() {
|
bool update(bool writeprotected) {
|
||||||
writeLog("Update started..");
|
writeLog("Update started..");
|
||||||
|
|
||||||
string updDir = workDir + "tupdates/temp", readyFilePath = workDir + "tupdates/temp/ready", tdataDir = workDir + "tupdates/temp/tdata";
|
string updDir = workDir + "tupdates/temp", readyFilePath = workDir + "tupdates/temp/ready", tdataDir = workDir + "tupdates/temp/tdata";
|
||||||
|
@ -346,7 +347,7 @@ bool update() {
|
||||||
writeLog("Copying file '%s' to '%s'..", fname.c_str(), tofname.c_str());
|
writeLog("Copying file '%s' to '%s'..", fname.c_str(), tofname.c_str());
|
||||||
int copyTries = 0, triesLimit = 30;
|
int copyTries = 0, triesLimit = 30;
|
||||||
do {
|
do {
|
||||||
if (!copyFile(fname.c_str(), tofname.c_str())) {
|
if (!copyFile(fname.c_str(), tofname.c_str(), writeprotected)) {
|
||||||
++copyTries;
|
++copyTries;
|
||||||
usleep(100000);
|
usleep(100000);
|
||||||
} else {
|
} else {
|
||||||
|
@ -381,6 +382,7 @@ int main(int argc, char *argv[]) {
|
||||||
bool needupdate = true;
|
bool needupdate = true;
|
||||||
bool autostart = false;
|
bool autostart = false;
|
||||||
bool debug = false;
|
bool debug = false;
|
||||||
|
bool writeprotected = false;
|
||||||
bool tosettings = false;
|
bool tosettings = false;
|
||||||
bool startintray = false;
|
bool startintray = false;
|
||||||
bool testmode = false;
|
bool testmode = false;
|
||||||
|
@ -389,6 +391,8 @@ int main(int argc, char *argv[]) {
|
||||||
|
|
||||||
char *key = 0;
|
char *key = 0;
|
||||||
char *workdir = 0;
|
char *workdir = 0;
|
||||||
|
char *oldUsername = 0;
|
||||||
|
char *dbusAddress = 0;
|
||||||
for (int i = 1; i < argc; ++i) {
|
for (int i = 1; i < argc; ++i) {
|
||||||
if (equal(argv[i], "-noupdate")) {
|
if (equal(argv[i], "-noupdate")) {
|
||||||
needupdate = false;
|
needupdate = false;
|
||||||
|
@ -408,12 +412,17 @@ int main(int argc, char *argv[]) {
|
||||||
customWorkingDir = true;
|
customWorkingDir = true;
|
||||||
} else if (equal(argv[i], "-key") && ++i < argc) {
|
} else if (equal(argv[i], "-key") && ++i < argc) {
|
||||||
key = argv[i];
|
key = argv[i];
|
||||||
|
} else if (equal(argv[i], "-writeprotected") && ++i < argc) {
|
||||||
|
writeprotected = true;
|
||||||
|
oldUsername = argv[i];
|
||||||
} else if (equal(argv[i], "-workpath") && ++i < argc) {
|
} else if (equal(argv[i], "-workpath") && ++i < argc) {
|
||||||
workDir = workdir = argv[i];
|
workDir = workdir = argv[i];
|
||||||
} else if (equal(argv[i], "-exename") && ++i < argc) {
|
} else if (equal(argv[i], "-exename") && ++i < argc) {
|
||||||
exeName = argv[i];
|
exeName = argv[i];
|
||||||
} else if (equal(argv[i], "-exepath") && ++i < argc) {
|
} else if (equal(argv[i], "-exepath") && ++i < argc) {
|
||||||
exePath = argv[i];
|
exePath = argv[i];
|
||||||
|
} else if (equal(argv[i], "-dbus") && ++i < argc) {
|
||||||
|
dbusAddress = argv[i];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (exeName.empty() || exeName.find('/') != string::npos) {
|
if (exeName.empty() || exeName.find('/') != string::npos) {
|
||||||
|
@ -427,6 +436,7 @@ int main(int argc, char *argv[]) {
|
||||||
}
|
}
|
||||||
if (needupdate) writeLog("Need to update!");
|
if (needupdate) writeLog("Need to update!");
|
||||||
if (autostart) writeLog("From autostart!");
|
if (autostart) writeLog("From autostart!");
|
||||||
|
if (writeprotected) writeLog("Write Protected folder!");
|
||||||
|
|
||||||
updaterName = CurrentExecutablePath(argc, argv);
|
updaterName = CurrentExecutablePath(argc, argv);
|
||||||
writeLog("Updater binary full path is: %s", updaterName.c_str());
|
writeLog("Updater binary full path is: %s", updaterName.c_str());
|
||||||
|
@ -477,7 +487,7 @@ int main(int argc, char *argv[]) {
|
||||||
} else {
|
} else {
|
||||||
writeLog("Passed workpath is '%s'", workDir.c_str());
|
writeLog("Passed workpath is '%s'", workDir.c_str());
|
||||||
}
|
}
|
||||||
update();
|
update(writeprotected);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
writeLog("Error: bad exe name!");
|
writeLog("Error: bad exe name!");
|
||||||
|
@ -494,6 +504,15 @@ int main(int argc, char *argv[]) {
|
||||||
// Force null-terminated .data() call result.
|
// Force null-terminated .data() call result.
|
||||||
values.push_back(arg + char(0));
|
values.push_back(arg + char(0));
|
||||||
};
|
};
|
||||||
|
if (writeprotected) { // run un-elevated
|
||||||
|
push("pkexec");
|
||||||
|
push("--user");
|
||||||
|
push(oldUsername);
|
||||||
|
push("env");
|
||||||
|
push("DBUS_SESSION_BUS_ADDRESS=" + string(dbusAddress));
|
||||||
|
push("systemd-run"); // restore environment
|
||||||
|
push("--user");
|
||||||
|
}
|
||||||
push(path);
|
push(path);
|
||||||
push("-noupdate");
|
push("-noupdate");
|
||||||
if (autostart) push("-autostart");
|
if (autostart) push("-autostart");
|
||||||
|
@ -523,10 +542,15 @@ int main(int argc, char *argv[]) {
|
||||||
writeLog("fork() failed!");
|
writeLog("fork() failed!");
|
||||||
return 1;
|
return 1;
|
||||||
case 0:
|
case 0:
|
||||||
execv(path, args.data());
|
execvp(args[0], args.data());
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// pkexec needs an alive parent
|
||||||
|
if (writeprotected) {
|
||||||
|
waitpid(pid, nullptr, 0);
|
||||||
|
}
|
||||||
|
|
||||||
writeLog("Executed Telegram, closing log and quitting..");
|
writeLog("Executed Telegram, closing log and quitting..");
|
||||||
closeLog();
|
closeLog();
|
||||||
|
|
||||||
|
|
|
@ -45,6 +45,10 @@ extern "C" {
|
||||||
#include <lzma.h>
|
#include <lzma.h>
|
||||||
#endif // else of Q_OS_WIN && !DESKTOP_APP_USE_PACKAGED
|
#endif // else of Q_OS_WIN && !DESKTOP_APP_USE_PACKAGED
|
||||||
|
|
||||||
|
#ifdef Q_OS_UNIX
|
||||||
|
#include <unistd.h>
|
||||||
|
#endif // Q_OS_UNIX
|
||||||
|
|
||||||
namespace Core {
|
namespace Core {
|
||||||
namespace {
|
namespace {
|
||||||
|
|
||||||
|
@ -1553,9 +1557,25 @@ bool checkReadyUpdate() {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
#elif defined Q_OS_UNIX // Q_OS_MAC
|
#elif defined Q_OS_UNIX // Q_OS_MAC
|
||||||
|
// if the files in the directory are owned by user, while the directory is not,
|
||||||
|
// update will still fail since it's not possible to remove files
|
||||||
|
if (unlink(QFile::encodeName(curUpdater).constData())) {
|
||||||
|
if (errno == EACCES) {
|
||||||
|
cSetWriteProtected(true);
|
||||||
|
return true;
|
||||||
|
} else {
|
||||||
|
ClearAll();
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
if (!linuxMoveFile(QFile::encodeName(updater.absoluteFilePath()).constData(), QFile::encodeName(curUpdater).constData())) {
|
if (!linuxMoveFile(QFile::encodeName(updater.absoluteFilePath()).constData(), QFile::encodeName(curUpdater).constData())) {
|
||||||
ClearAll();
|
if (errno == EACCES) {
|
||||||
return false;
|
cSetWriteProtected(true);
|
||||||
|
return true;
|
||||||
|
} else {
|
||||||
|
ClearAll();
|
||||||
|
return false;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
#endif // Q_OS_UNIX
|
#endif // Q_OS_UNIX
|
||||||
|
|
||||||
|
|
|
@ -14,6 +14,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
||||||
|
|
||||||
#include <sys/stat.h>
|
#include <sys/stat.h>
|
||||||
#include <sys/types.h>
|
#include <sys/types.h>
|
||||||
|
#include <sys/wait.h>
|
||||||
#include <cstdlib>
|
#include <cstdlib>
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
#include <dirent.h>
|
#include <dirent.h>
|
||||||
|
@ -75,12 +76,17 @@ bool Launcher::launchUpdater(UpdaterLaunch action) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
const auto binaryName = (action == UpdaterLaunch::JustRelaunch)
|
const auto binaryPath = (action == UpdaterLaunch::JustRelaunch)
|
||||||
? cExeName()
|
? (cExeDir() + cExeName())
|
||||||
: QStringLiteral("Updater");
|
: (cWriteProtected()
|
||||||
|
? (cWorkingDir() + qsl("tupdates/temp/Updater"))
|
||||||
|
: (cExeDir() + qsl("Updater")));
|
||||||
|
|
||||||
auto argumentsList = Arguments();
|
auto argumentsList = Arguments();
|
||||||
argumentsList.push(QFile::encodeName(cExeDir() + binaryName));
|
if (action != UpdaterLaunch::JustRelaunch && cWriteProtected()) {
|
||||||
|
argumentsList.push("pkexec");
|
||||||
|
}
|
||||||
|
argumentsList.push(QFile::encodeName(binaryPath));
|
||||||
|
|
||||||
if (cLaunchMode() == LaunchModeAutoStart) {
|
if (cLaunchMode() == LaunchModeAutoStart) {
|
||||||
argumentsList.push("-autostart");
|
argumentsList.push("-autostart");
|
||||||
|
@ -118,6 +124,16 @@ bool Launcher::launchUpdater(UpdaterLaunch action) {
|
||||||
if (customWorkingDir()) {
|
if (customWorkingDir()) {
|
||||||
argumentsList.push("-workdir_custom");
|
argumentsList.push("-workdir_custom");
|
||||||
}
|
}
|
||||||
|
if (cWriteProtected()) {
|
||||||
|
const auto currentUid = geteuid();
|
||||||
|
const auto pw = getpwuid(currentUid);
|
||||||
|
if (pw) {
|
||||||
|
argumentsList.push("-writeprotected");
|
||||||
|
argumentsList.push(pw->pw_name);
|
||||||
|
argumentsList.push("-dbus");
|
||||||
|
argumentsList.push(qgetenv("DBUS_SESSION_BUS_ADDRESS"));
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Logs::closeMain();
|
Logs::closeMain();
|
||||||
|
@ -128,8 +144,14 @@ bool Launcher::launchUpdater(UpdaterLaunch action) {
|
||||||
pid_t pid = fork();
|
pid_t pid = fork();
|
||||||
switch (pid) {
|
switch (pid) {
|
||||||
case -1: return false;
|
case -1: return false;
|
||||||
case 0: execv(args[0], args); return false;
|
case 0: execvp(args[0], args); return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// pkexec needs an alive parent
|
||||||
|
if (cWriteProtected()) {
|
||||||
|
waitpid(pid, nullptr, 0);
|
||||||
|
}
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Add table
Reference in a new issue