Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

support exporting UAB in "onlyApp" mode #953

Merged
merged 11 commits into from
Jan 7, 2025
Merged
5 changes: 5 additions & 0 deletions .reuse/dep5
Original file line number Diff line number Diff line change
Expand Up @@ -146,3 +146,8 @@ Copyright: UnionTech Software Technology Co., Ltd.
Files: misc/image/*.jpeg misc/image/*.svg
License: LGPL-3.0-or-later
Copyright: UnionTech Software Technology Co., Ltd.

# uab black list
Files: misc/share/linglong/builder/uab/blacklist
License: MIT
Copyright: AppImageCommunity
4 changes: 4 additions & 0 deletions api/schema/v1.json
Original file line number Diff line number Diff line change
Expand Up @@ -216,6 +216,10 @@
"type": "string",
"const": "1"
},
"onlyApp": {
"description": "whether this UAB file has been exported in only-App mode.",
"type": "boolean"
},
"sections": {
"type": "object",
"required": [
Expand Down
3 changes: 3 additions & 0 deletions api/schema/v1.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -181,6 +181,9 @@ $defs:
description: The format version of linglong.meta data.
type: string
const: '1'
onlyApp:
description: whether this UAB file has been exported in only-App mode.
type: boolean
sections:
type: object
required:
Expand Down
56 changes: 27 additions & 29 deletions apps/ll-box/src/container/container.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -362,8 +362,11 @@ struct ContainerPrivate
// default link
for (const auto &[from, to] : linkMap) {
if (auto ret = symlink(from.data(), to.data()); ret == -1) {
logErr() << "symlink" << from << "to" << to << "failed:" << util::RetErrString(ret);
return -1;
if (errno != EEXIST) {
logErr() << "symlink" << from << "to" << to
<< "failed:" << util::RetErrString(ret);
return -1;
}
}
}

Expand Down Expand Up @@ -545,49 +548,44 @@ struct ContainerPrivate
return -1;
}

int flag = MS_BIND | MS_REC;
ret = mount(".", ".", "bind", flag, nullptr);
if (0 != ret) {
int flag = MS_SILENT | MS_BIND | MS_REC;
ret = mount(".", ".", nullptr, flag, nullptr);
if (ret < 0) {
logErr() << "mount / failed" << util::RetErrString(ret);
return -1;
}

const auto *llHostFilename = "ll-host";
auto llHostInPath = std::string{ "/run/" } + llHostFilename;
auto llHostOutPath = hostRoot + llHostInPath;
ret = mkdir(llHostOutPath.c_str(), 0755);
if (ret != 0) {
logErr() << "mkdir" << llHostOutPath << "err:" << util::RetErrString(ret);
return -1;
}

ret = syscall(SYS_pivot_root, hostRoot.c_str(), llHostOutPath.c_str());
if (0 != ret) {
logErr() << "SYS_pivot_root failed" << hostRoot << util::errnoString() << errno << ret;
// pivot with fd
int oldRootFd = open("/", O_DIRECTORY | O_PATH | O_CLOEXEC);
int newRootFd = open(hostRoot.c_str(), O_DIRECTORY | O_RDONLY | O_CLOEXEC);
ret = fchdir(newRootFd);
if (ret < 0) {
logErr() << "fchdir new root" << newRootFd << "failed:" << util::RetErrString(ret);
return -1;
}

ret = chdir("/");
if (ret != 0) {
logErr() << "chdir to root [before chroot]:" << util::RetErrString(ret);
ret = syscall(SYS_pivot_root, ".", ".");
if (ret < 0) {
logErr() << "SYS_pivot_root" << hostRoot << "failed:" << util::errnoString() << errno
<< ret;
return -1;
}

ret = chroot(".");
if (0 != ret) {
logErr() << "chroot failed" << hostRoot << util::errnoString() << errno;
ret = fchdir(oldRootFd);
if (ret < 0) {
logErr() << "fchdir old root" << oldRootFd << "failed:" << util::RetErrString(ret);
return -1;
}

ret = chdir("/");
if (ret != 0) {
logErr() << "chdir to root [after chroot]:" << util::RetErrString(ret);
ret = mount(".", ".", NULL, MS_SILENT | MS_REC | MS_PRIVATE, NULL);
if (ret < 0) {
logErr() << "mount old root" << oldRootFd << "failed:" << util::RetErrString(ret);
return -1;
}

ret = umount2(llHostInPath.c_str(), MNT_DETACH);
if (ret != 0) {
logErr() << "umount2" << llHostInPath << "err:" << util::RetErrString(ret);
ret = umount2(".", MNT_DETACH);
if (ret < 0) {
logErr() << "umount old root" << oldRootFd << "failed:" << util::RetErrString(ret);
return -1;
}

Expand Down
6 changes: 5 additions & 1 deletion apps/ll-box/src/container/mount/filesystem_driver.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -6,12 +6,13 @@

#include "filesystem_driver.h"

#include "util/logger.h"

Check warning on line 9 in apps/ll-box/src/container/mount/filesystem_driver.cpp

View workflow job for this annotation

GitHub Actions / cppcheck

Include file: "util/logger.h" not found.
#include "util/platform.h"

Check warning on line 10 in apps/ll-box/src/container/mount/filesystem_driver.cpp

View workflow job for this annotation

GitHub Actions / cppcheck

Include file: "util/platform.h" not found.

#include <cerrno>

Check warning on line 12 in apps/ll-box/src/container/mount/filesystem_driver.cpp

View workflow job for this annotation

GitHub Actions / cppcheck

Include file: <cerrno> not found. Please note: Cppcheck does not need standard library headers to get proper results.
#include <utility>

Check warning on line 13 in apps/ll-box/src/container/mount/filesystem_driver.cpp

View workflow job for this annotation

GitHub Actions / cppcheck

Include file: <utility> not found. Please note: Cppcheck does not need standard library headers to get proper results.

#include <sys/wait.h>

Check warning on line 15 in apps/ll-box/src/container/mount/filesystem_driver.cpp

View workflow job for this annotation

GitHub Actions / cppcheck

Include file: <sys/wait.h> not found. Please note: Cppcheck does not need standard library headers to get proper results.

namespace linglong {

Expand Down Expand Up @@ -97,7 +98,10 @@

auto host_destination_path = util::fs::path(root_path_) / container_destination_path;

util::fs::create_directories(host_destination_path, dest_mode);
if (!util::fs::create_directories(host_destination_path, dest_mode)) {
logErr() << "failed to create" << host_destination_path;
return -1;
}

return 0;
}
Expand Down
3 changes: 2 additions & 1 deletion apps/ll-box/src/util/filesystem.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -40,10 +40,11 @@ bool create_directories(const path &p, __mode_t mode)

auto ret = mkdir(fullPath.c_str(), mode);
if (0 != ret) {
logErr() << util::RetErrString(errno) << fullPath << mode;
logErr() << util::RetErrString(ret) << fullPath << mode;
return false;
}
}

return true;
}

Expand Down
12 changes: 5 additions & 7 deletions apps/ll-builder/src/main.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -285,16 +285,17 @@ You can report bugs to the linyaps team under this project: https://github.com/O

// build export
bool layerMode = false;
std::string iconFile;
auto buildExport = commandParser.add_subcommand("export", _("Export to linyaps layer or uab"));
linglong::builder::UABOption UABOption{ .exportDevelop = false, .exportI18n = true };
auto *buildExport = commandParser.add_subcommand("export", _("Export to linyaps layer or uab"));
buildExport->usage(_("Usage: ll-builder export [OPTIONS]"));
buildExport->add_option("-f, --file", filePath, _("File path of the linglong.yaml"))
->type_name("FILE")
->capture_default_str()
->check(CLI::ExistingFile);
buildExport->add_option("--icon", iconFile, _("Uab icon (optional)"))
buildExport->add_option("--icon", UABOption.iconPath, _("Uab icon (optional)"))
->type_name("FILE")
->check(CLI::ExistingFile);
buildExport->add_flag("--only-app", UABOption.onlyApp, _("Export uab in only-app mode"));
buildExport->add_flag("--layer", layerMode, _("Export to linyaps layer file"));

// build push
Expand Down Expand Up @@ -759,10 +760,7 @@ You can report bugs to the linyaps team under this project: https://github.com/O
return 0;
}

auto result = builder.exportUAB(QDir::currentPath(),
{ .iconPath = QString::fromStdString(iconFile),
.exportDevelop = true,
.exportI18n = true });
auto result = builder.exportUAB(QDir::currentPath(), UABOption);
if (!result) {
qCritical() << result.error();
return -1;
Expand Down
15 changes: 13 additions & 2 deletions apps/uab/header/src/main.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,10 @@ std::string resolveRealPath(std::string_view source) noexcept

std::string detectLinglong() noexcept
{
if (::getenv("LINGLONG_UAB_DIRECT_EXEC") != nullptr) {
return {};
}

auto *pathPtr = ::getenv("PATH");
if (pathPtr == nullptr) {
std::cerr << "failed to get PATH" << std::endl;
Expand Down Expand Up @@ -464,7 +468,8 @@ int extractBundle(std::string_view destination) noexcept
return 0;
}

[[noreturn]] void runAppLoader(const std::vector<std::string_view> &loaderArgs) noexcept
[[noreturn]] void runAppLoader(bool onlyApp,
const std::vector<std::string_view> &loaderArgs) noexcept
{
auto loader = mountPoint / "loader";
auto loaderStr = loader.string();
Expand Down Expand Up @@ -492,6 +497,12 @@ int extractBundle(std::string_view destination) noexcept
}

if (loaderPid == 0) {
std::string_view newEnv{ "LINGLONG_UAB_LOADER_ONLY_APP=true" };
if (onlyApp && ::putenv(const_cast<char *>(newEnv.data())) < 0) {
std::cerr << "putenv error: " << ::strerror(errno) << std::endl;
cleanAndExit(errno);
}

if (::execv(loaderStr.c_str(), reinterpret_cast<char *const *>(const_cast<char **>(argv)))
== -1) {
std::cerr << "execv(" << loaderStr << ") error: " << ::strerror(errno) << std::endl;
Expand Down Expand Up @@ -693,5 +704,5 @@ int main(int argc, char **argv)
cleanAndExit(-1);
}

runAppLoader(opts.loaderArgs);
runAppLoader(metaInfo.onlyApp.value_or(false), opts.loaderArgs);
}
Loading
Loading