|
25 | 25 | #include "linglong/api/types/v1/State.hpp" |
26 | 26 | #include "linglong/api/types/v1/UpgradeListResult.hpp" |
27 | 27 | #include "linglong/cli/printer.h" |
| 28 | +#include "linglong/cli/extension_override.h" |
28 | 29 | #include "linglong/common/dir.h" |
29 | 30 | #include "linglong/common/strings.h" |
30 | 31 | #include "linglong/oci-cfg-generators/container_cfg_builder.h" |
|
58 | 59 | #include <cstdint> |
59 | 60 | #include <cstdlib> |
60 | 61 | #include <filesystem> |
| 62 | +#include <fstream> |
61 | 63 | #include <iostream> |
| 64 | +#include <map> |
62 | 65 | #include <optional> |
63 | 66 | #include <system_error> |
64 | 67 | #include <thread> |
|
67 | 70 |
|
68 | 71 | #include <fcntl.h> |
69 | 72 | #include <sys/mman.h> |
| 73 | +#include <sys/resource.h> |
70 | 74 | #include <unistd.h> |
71 | 75 |
|
72 | 76 | using namespace linglong::utils::error; |
@@ -519,10 +523,21 @@ int Cli::run(const RunOptions &options) |
519 | 523 | linglong::runtime::ResolveOptions opts; |
520 | 524 | opts.baseRef = options.base; |
521 | 525 | opts.runtimeRef = options.runtime; |
522 | | - // 处理多个扩展 |
523 | 526 | if (!options.extensions.empty()) { |
524 | 527 | opts.extensionRefs = options.extensions; |
525 | 528 | } |
| 529 | + auto configPath = extension_override::getUserConfigPath(); |
| 530 | + if (configPath) { |
| 531 | + auto overrides = extension_override::loadOverrides(*configPath); |
| 532 | + if (overrides) { |
| 533 | + if (!overrides->empty()) { |
| 534 | + runContext.setExtensionOverrides(std::move(*overrides)); |
| 535 | + } |
| 536 | + } else { |
| 537 | + qWarning() << "failed to load extension overrides:" |
| 538 | + << overrides.error().message().c_str(); |
| 539 | + } |
| 540 | + } |
526 | 541 |
|
527 | 542 | // 调整日志输出,打印扩展列表(用逗号拼接) |
528 | 543 | std::string extStr = |
@@ -2137,6 +2152,22 @@ utils::error::Result<void> Cli::generateLDCache(runtime::RunContext &runContext, |
2137 | 2152 | { |
2138 | 2153 | LINGLONG_TRACE("generate ld cache"); |
2139 | 2154 |
|
| 2155 | + { |
| 2156 | + struct rlimit limit {}; |
| 2157 | + if (::getrlimit(RLIMIT_NOFILE, &limit) == 0) { |
| 2158 | + rlim_t target = limit.rlim_max; |
| 2159 | + if (target == RLIM_INFINITY) { |
| 2160 | + target = 65535; |
| 2161 | + } |
| 2162 | + if (limit.rlim_cur < target) { |
| 2163 | + struct rlimit newLimit { target, limit.rlim_max }; |
| 2164 | + if (::setrlimit(RLIMIT_NOFILE, &newLimit) != 0) { |
| 2165 | + qWarning() << "failed to raise RLIMIT_NOFILE:" << ::strerror(errno); |
| 2166 | + } |
| 2167 | + } |
| 2168 | + } |
| 2169 | + } |
| 2170 | + |
2140 | 2171 | auto appLayerItem = runContext.getCachedAppItem(); |
2141 | 2172 | if (!appLayerItem) { |
2142 | 2173 | return LINGLONG_ERR(appLayerItem); |
@@ -2211,6 +2242,28 @@ utils::error::Result<void> Cli::generateLDCache(runtime::RunContext &runContext, |
2211 | 2242 | process.args = |
2212 | 2243 | std::vector<std::string>{ "/sbin/ldconfig", "-X", "-C", "/run/linglong/cache/ld.so.cache" }; |
2213 | 2244 |
|
| 2245 | + { |
| 2246 | + // Ensure ldconfig inside the container has a sufficiently large FD limit. |
| 2247 | + // Raising RLIMIT_NOFILE only on the host process may not reliably propagate |
| 2248 | + // into the OCI process, depending on the runtime's defaults. |
| 2249 | + rlim_t target = 65535; |
| 2250 | + struct rlimit limit {}; |
| 2251 | + if (::getrlimit(RLIMIT_NOFILE, &limit) == 0) { |
| 2252 | + if (limit.rlim_max != RLIM_INFINITY) { |
| 2253 | + target = limit.rlim_max; |
| 2254 | + } |
| 2255 | + } |
| 2256 | + if (target == RLIM_INFINITY) { |
| 2257 | + target = 65535; |
| 2258 | + } |
| 2259 | + int64_t nofile = static_cast<int64_t>(target); |
| 2260 | + process.rlimits = std::vector<ocppi::runtime::config::types::Rlimit>{ |
| 2261 | + ocppi::runtime::config::types::Rlimit{ .hard = nofile, |
| 2262 | + .soft = nofile, |
| 2263 | + .type = "RLIMIT_NOFILE" }, |
| 2264 | + }; |
| 2265 | + } |
| 2266 | + |
2214 | 2267 | ocppi::runtime::RunOption opt{}; |
2215 | 2268 | auto result = (*container)->run(process, opt); |
2216 | 2269 | if (!result) { |
@@ -2327,6 +2380,21 @@ int Cli::inspect(CLI::App *app, const InspectOptions &options) |
2327 | 2380 | return 0; |
2328 | 2381 | } |
2329 | 2382 |
|
| 2383 | +int Cli::extension(CLI::App *app, const ExtensionOptions &options) |
| 2384 | +{ |
| 2385 | + LINGLONG_TRACE("command extension"); |
| 2386 | + |
| 2387 | + auto argsParseFunc = [&app](const std::string &name) -> bool { |
| 2388 | + return app->get_subcommand(name)->parsed(); |
| 2389 | + }; |
| 2390 | + |
| 2391 | + if (argsParseFunc("import-cdi")) { |
| 2392 | + return importCdi(options); |
| 2393 | + } |
| 2394 | + |
| 2395 | + return 0; |
| 2396 | +} |
| 2397 | + |
2330 | 2398 | int Cli::getLayerDir(const InspectOptions &options) |
2331 | 2399 | { |
2332 | 2400 | LINGLONG_TRACE("Get Layer dir"); |
@@ -2388,6 +2456,35 @@ int Cli::getBundleDir(const InspectOptions &options) |
2388 | 2456 | return 0; |
2389 | 2457 | } |
2390 | 2458 |
|
| 2459 | +int Cli::importCdi(const ExtensionOptions &options) |
| 2460 | +{ |
| 2461 | + LINGLONG_TRACE("import CDI config"); |
| 2462 | + |
| 2463 | + std::filesystem::path configPath; |
| 2464 | + if (options.configPath) { |
| 2465 | + configPath = *options.configPath; |
| 2466 | + } else { |
| 2467 | + auto userConfigPath = extension_override::getUserConfigPath(); |
| 2468 | + if (!userConfigPath) { |
| 2469 | + this->printer.printErr(LINGLONG_ERRV("failed to resolve user config path")); |
| 2470 | + return -1; |
| 2471 | + } |
| 2472 | + configPath = *userConfigPath; |
| 2473 | + } |
| 2474 | + |
| 2475 | + auto res = extension_override::importCdiOverrides(configPath, |
| 2476 | + options.cdiPath, |
| 2477 | + options.name, |
| 2478 | + !options.applyWhenInstalled); |
| 2479 | + if (!res) { |
| 2480 | + this->printer.printErr(res.error()); |
| 2481 | + return -1; |
| 2482 | + } |
| 2483 | + |
| 2484 | + this->printer.printMessage("CDI config imported into " + configPath.string()); |
| 2485 | + return 0; |
| 2486 | +} |
| 2487 | + |
2391 | 2488 | utils::error::Result<void> Cli::initInteraction() |
2392 | 2489 | { |
2393 | 2490 | LINGLONG_TRACE("initInteraction"); |
|
0 commit comments