MCPcopy Create free account
hub / github.com/TheAssassin/AppImageLauncher / runAppImage

Function runAppImage

src/ui/main.cpp:38–95  ·  view source on GitHub ↗

Runs an AppImage. Returns suitable exit code for main application.

Source from the content-addressed store, hash-verified

36
37// Runs an AppImage. Returns suitable exit code for main application.
38int runAppImage(const QString& pathToAppImage, unsigned long argc, char** argv) {
39 // needs to be converted to std::string to be able to use c_str()
40 // when using QString and then .toStdString().c_str(), the std::string instance will be an rvalue, and the
41 // pointer returned by c_str() will be invalid
42 auto fullPathToAppImage = QFileInfo(pathToAppImage).absoluteFilePath();
43
44 auto type = appimage_get_type(fullPathToAppImage.toStdString().c_str(), false);
45 if (type < 1 || type > 3) {
46 displayError(QObject::tr("AppImageLauncher does not support type %1 AppImages at the moment.").arg(type));
47 return 1;
48 }
49
50 // first of all, chmod +x the AppImage registerFile
51 // be happy the registerFile is executable already
52 if (!makeExecutable(fullPathToAppImage)) {
53 displayError(QObject::tr("Could not make AppImage executable: %1").arg(fullPathToAppImage));
54 return 1;
55 }
56
57 // suppress desktop integration script etc.
58 setenv("DESKTOPINTEGRATION", "AppImageLauncher", true);
59
60 auto makeVectorBuffer = [](const std::string& str) {
61 std::vector<char> strBuffer(str.size() + 1, '\0');
62 strncpy(strBuffer.data(), str.c_str(), str.size());
63 return strBuffer;
64 };
65
66 // calculate buffer to bypass binary
67 std::string pathToBinfmtBypassLauncher = privateLibDirPath("binfmt-bypass").toStdString() + "/binfmt-bypass";
68
69 // create new args array for exec()d process
70 std::vector<char*> args;
71
72 // first argument is the path to our launcher
73 auto pathToBinfmtBypassLauncherBuffer = makeVectorBuffer(pathToBinfmtBypassLauncher);
74 args.push_back(pathToBinfmtBypassLauncherBuffer.data());
75
76 // first argument is consumed by the bypass launcher
77 // the reason we launch the bypass launcher as a new process to save RAM (we have to launch the actual AppImage
78 // as a subprocess, and the launcher executable has a much lower memory footprint)
79 auto pathToAppImageBuffer = makeVectorBuffer(pathToAppImage.toStdString());
80 args.push_back(pathToAppImageBuffer.data());
81
82 // copy arguments
83 for (unsigned long i = 1; i < argc; i++) {
84 args.push_back(argv[i]);
85 }
86
87 // args need to be null terminated
88 args.push_back(nullptr);
89
90 execv(pathToBinfmtBypassLauncher.c_str(), args.data());
91
92 const auto& error = errno;
93 std::cerr << QObject::tr("execv() failed: %1").arg(strerror(error)).toStdString() << std::endl;
94 return 1;
95}

Callers 1

mainFunction · 0.85

Calls 3

displayErrorFunction · 0.85
makeExecutableFunction · 0.85
privateLibDirPathFunction · 0.85

Tested by

no test coverage detected