Beta version 4.9.10: Fix after-update relaunch.

This commit is contained in:
John Preston 2023-09-22 14:43:59 +04:00
parent 9604a3bd80
commit 89fac88677
2 changed files with 146 additions and 61 deletions

View File

@ -47,6 +47,7 @@ string updaterName;
string workDir;
string exeName;
string exePath;
string argv0;
FILE *_logFile = 0;
void openLog() {
@ -356,17 +357,44 @@ string CurrentExecutablePath(int argc, char *argv[]) {
}
int main(int argc, char *argv[]) {
bool needupdate = true;
bool autostart = false;
bool debug = false;
bool tosettings = false;
bool startintray = false;
bool customWorkingDir = false;
bool justUpdate = false;
char *key = 0;
char *workdir = 0;
for (int i = 1; i < argc; ++i) {
if (equal(argv[i], "-debug")) {
_debug = true;
if (equal(argv[i], "-noupdate")) {
needupdate = false;
} else if (equal(argv[i], "-autostart")) {
autostart = true;
} else if (equal(argv[i], "-debug")) {
debug = _debug = true;
} else if (equal(argv[i], "-startintray")) {
startintray = true;
} else if (equal(argv[i], "-tosettings")) {
tosettings = true;
} else if (equal(argv[i], "-workdir_custom")) {
customWorkingDir = true;
} else if (equal(argv[i], "-writeprotected")) {
writeprotected = true;
justUpdate = true;
} else if (equal(argv[i], "-justupdate")) {
justUpdate = true;
} else if (equal(argv[i], "-key") && ++i < argc) {
key = argv[i];
} else if (equal(argv[i], "-workpath") && ++i < argc) {
workDir = argv[i];
workDir = workdir = argv[i];
} else if (equal(argv[i], "-exename") && ++i < argc) {
exeName = argv[i];
} else if (equal(argv[i], "-exepath") && ++i < argc) {
exePath = argv[i];
} else if (equal(argv[i], "-argv0") && ++i < argc) {
argv0 = argv[i];
}
}
if (exeName.empty() || exeName.find('/') != string::npos) {
@ -378,6 +406,8 @@ int main(int argc, char *argv[]) {
for (int i = 0; i < argc; ++i) {
writeLog("Argument: '%s'", argv[i]);
}
if (needupdate) writeLog("Need to update!");
if (autostart) writeLog("From autostart!");
if (writeprotected) writeLog("Write Protected folder!");
updaterName = CurrentExecutablePath(argc, argv);
@ -395,38 +425,42 @@ int main(int argc, char *argv[]) {
exePath = updaterDir;
writeLog("Using updater binary dir.", exePath.c_str());
}
if (workDir.empty()) { // old app launched, update prepared in tupdates/ready (not in tupdates/temp)
writeLog("No workdir, trying to figure it out");
struct passwd *pw = getpwuid(getuid());
if (pw && pw->pw_dir && strlen(pw->pw_dir)) {
string tryDir = pw->pw_dir + string("/.TelegramDesktop/");
struct stat statbuf;
writeLog("Trying to use '%s' as workDir, getting stat() for tupdates/ready", tryDir.c_str());
if (!stat((tryDir + "tupdates/ready").c_str(), &statbuf)) {
writeLog("Stat got");
if (S_ISDIR(statbuf.st_mode)) {
writeLog("It is directory, using home work dir");
workDir = tryDir;
}
}
}
if (workDir.empty()) {
workDir = exePath;
if (needupdate) {
if (workDir.empty()) { // old app launched, update prepared in tupdates/ready (not in tupdates/temp)
customWorkingDir = false;
struct stat statbuf;
writeLog("Trying to use current as workDir, getting stat() for tupdates/ready");
if (!stat("tupdates/ready", &statbuf)) {
writeLog("Stat got");
if (S_ISDIR(statbuf.st_mode)) {
writeLog("It is directory, using current dir");
workDir = string();
writeLog("No workdir, trying to figure it out");
struct passwd *pw = getpwuid(getuid());
if (pw && pw->pw_dir && strlen(pw->pw_dir)) {
string tryDir = pw->pw_dir + string("/.TelegramDesktop/");
struct stat statbuf;
writeLog("Trying to use '%s' as workDir, getting stat() for tupdates/ready", tryDir.c_str());
if (!stat((tryDir + "tupdates/ready").c_str(), &statbuf)) {
writeLog("Stat got");
if (S_ISDIR(statbuf.st_mode)) {
writeLog("It is directory, using home work dir");
workDir = tryDir;
}
}
}
if (workDir.empty()) {
workDir = exePath;
struct stat statbuf;
writeLog("Trying to use current as workDir, getting stat() for tupdates/ready");
if (!stat("tupdates/ready", &statbuf)) {
writeLog("Stat got");
if (S_ISDIR(statbuf.st_mode)) {
writeLog("It is directory, using current dir");
workDir = string();
}
}
}
} else {
writeLog("Passed workpath is '%s'", workDir.c_str());
}
} else {
writeLog("Passed workpath is '%s'", workDir.c_str());
update();
}
update();
} else {
writeLog("Error: bad exe name!");
}
@ -434,7 +468,51 @@ int main(int argc, char *argv[]) {
writeLog("Error: short exe name!");
}
writeLog("Closing log and quitting..");
// let the parent launch instead
if (justUpdate) {
writeLog("Closing log and quitting..");
} else {
const auto fullBinaryPath = exePath + exeName;
auto values = vector<string>();
const auto push = [&](string arg) {
// Force null-terminated .data() call result.
values.push_back(arg + char(0));
};
push(!argv0.empty() ? argv0 : fullBinaryPath);
push("-noupdate");
if (autostart) push("-autostart");
if (debug) push("-debug");
if (startintray) push("-startintray");
if (tosettings) push("-tosettings");
if (key) {
push("-key");
push(key);
}
if (customWorkingDir && workdir) {
push("-workdir");
push(workdir);
}
auto args = vector<char*>();
for (auto &arg : values) {
args.push_back(arg.data());
}
args.push_back(nullptr);
pid_t pid = fork();
switch (pid) {
case -1:
writeLog("fork() failed!");
return 1;
case 0:
execv(fullBinaryPath.c_str(), args.data());
return 1;
}
writeLog("Executed Telegram, closing log and quitting..");
}
closeLog();
return 0;

View File

@ -44,21 +44,27 @@ bool Launcher::launchUpdater(UpdaterLaunch action) {
const auto justRelaunch = action == UpdaterLaunch::JustRelaunch;
const auto binaryPath = justRelaunch
? (cExeDir() + cExeName()).toStdString()
: (cWriteProtected()
? (cWorkingDir() + u"tupdates/temp/Updater"_q)
: (cExeDir() + u"Updater"_q)).toStdString();
std::vector<std::string> argumentsList;
if (justRelaunch) {
argumentsList.push_back(binaryPath);
} else if (cWriteProtected()) {
argumentsList.push_back("pkexec");
// What we are launching.
const auto launching = justRelaunch
? (cExeDir() + cExeName())
: cWriteProtected()
? u"pkexec"_q
: (cExeDir() + u"Updater"_q);
argumentsList.push_back(launching.toStdString());
// argv[0] that is passed to what we are launching.
const auto argv0 = (justRelaunch && !arguments().isEmpty())
? arguments().first()
: launching;
argumentsList.push_back(argv0.toStdString());
if (!justRelaunch && cWriteProtected()) {
// Elevated process that pkexec should launch.
const auto elevated = cWorkingDir() + u"tupdates/temp/Updater"_q;
argumentsList.push_back(elevated.toStdString());
}
argumentsList.push_back((justRelaunch && !arguments().isEmpty())
? arguments().first().toStdString()
: binaryPath);
if (Logs::DebugEnabled()) {
argumentsList.push_back("-debug");
@ -82,6 +88,9 @@ bool Launcher::launchUpdater(UpdaterLaunch action) {
argumentsList.push_back(cWorkingDir().toStdString());
}
} else {
// Don't relaunch Telegram.
argumentsList.push_back("-justupdate");
argumentsList.push_back("-workpath");
argumentsList.push_back(cWorkingDir().toStdString());
argumentsList.push_back("-exename");
@ -105,24 +114,22 @@ bool Launcher::launchUpdater(UpdaterLaunch action) {
nullptr,
nullptr,
nullptr);
} else {
if (!GLib::spawn_sync(
argumentsList,
std::nullopt,
// if the spawn is sync, working directory is not set
// and GLib::SpawnFlags::LEAVE_DESCRIPTORS_OPEN_ is set,
// it goes through an optimized code path
GLib::SpawnFlags::SEARCH_PATH_
| GLib::SpawnFlags::LEAVE_DESCRIPTORS_OPEN_,
nullptr,
nullptr,
nullptr,
nullptr,
nullptr)) {
return false;
}
return launchUpdater(UpdaterLaunch::JustRelaunch);
} else if (!GLib::spawn_sync(
argumentsList,
std::nullopt,
// if the spawn is sync, working directory is not set
// and GLib::SpawnFlags::LEAVE_DESCRIPTORS_OPEN_ is set,
// it goes through an optimized code path
GLib::SpawnFlags::SEARCH_PATH_
| GLib::SpawnFlags::LEAVE_DESCRIPTORS_OPEN_,
nullptr,
nullptr,
nullptr,
nullptr,
nullptr)) {
return false;
}
return launchUpdater(UpdaterLaunch::JustRelaunch);
}
} // namespace