X-Git-Url: https://git.saurik.com/apt.git/blobdiff_plain/8d6d3f00b14217e69ecabd68379b1e29bf4a3ccd..8d0d92558c00d1825e413ce67be51a46a5c18aea:/apt-pkg/deb/debsystem.cc?ds=sidebyside diff --git a/apt-pkg/deb/debsystem.cc b/apt-pkg/deb/debsystem.cc index 5353761fc..56ca8f4c6 100644 --- a/apt-pkg/deb/debsystem.cc +++ b/apt-pkg/deb/debsystem.cc @@ -302,31 +302,62 @@ void debSystem::DpkgChrootDirectory() /*{{{*/ _exit(100); } /*}}}*/ -bool debSystem::SupportsMultiArch() /*{{{*/ +pid_t debSystem::ExecDpkg(std::vector const &sArgs, int * const inputFd, int * const outputFd, bool const DiscardOutput)/*{{{*/ { - // Generate the base argument list for dpkg - std::vector const Args = GetDpkgBaseCommand(); - std::vector cArgs(Args.size(), NULL); - std::transform(Args.begin(), Args.end(), cArgs.begin(), [](std::string const &s) { return s.c_str(); }); + std::vector Args(sArgs.size(), NULL); + std::transform(sArgs.begin(), sArgs.end(), Args.begin(), [](std::string const &s) { return s.c_str(); }); + Args.push_back(NULL); - // we need to detect if we can qualify packages with the architecture or not - cArgs.push_back("--assert-multi-arch"); - cArgs.push_back(NULL); + int external[2] = {-1, -1}; + if (inputFd != nullptr || outputFd != nullptr) + if (pipe(external) != 0) + { + _error->WarningE("dpkg", "Can't create IPC pipe for dpkg call"); + return -1; + } - pid_t dpkgAssertMultiArch = ExecFork(); - if (dpkgAssertMultiArch == 0) - { - DpkgChrootDirectory(); - // redirect everything to the ultimate sink as we only need the exit-status + pid_t const dpkg = ExecFork(); + if (dpkg == 0) { int const nullfd = open("/dev/null", O_RDONLY); - dup2(nullfd, STDIN_FILENO); - dup2(nullfd, STDOUT_FILENO); - dup2(nullfd, STDERR_FILENO); - execvp(cArgs[0], (char**) &cArgs[0]); - _error->WarningE("dpkgGo", "Can't detect if dpkg supports multi-arch!"); - _exit(2); + if (inputFd == nullptr) + dup2(nullfd, STDIN_FILENO); + else + { + close(external[1]); + dup2(external[0], STDIN_FILENO); + } + if (outputFd == nullptr) + dup2(nullfd, STDOUT_FILENO); + else + { + close(external[0]); + dup2(external[1], STDOUT_FILENO); + } + if (DiscardOutput == true) + dup2(nullfd, STDERR_FILENO); + debSystem::DpkgChrootDirectory(); + execvp(Args[0], (char**) &Args[0]); + _error->WarningE("dpkg", "Can't execute dpkg!"); + _exit(100); } - + if (outputFd != nullptr) + { + close(external[1]); + *outputFd = external[0]; + } + else if (inputFd != nullptr) + { + close(external[0]); + *inputFd = external[1]; + } + return dpkg; +} + /*}}}*/ +bool debSystem::SupportsMultiArch() /*{{{*/ +{ + std::vector Args = GetDpkgBaseCommand(); + Args.push_back("--assert-multi-arch"); + pid_t const dpkgAssertMultiArch = ExecDpkg(Args, nullptr, nullptr, true); if (dpkgAssertMultiArch > 0) { int Status = 0; @@ -343,3 +374,46 @@ bool debSystem::SupportsMultiArch() /*{{{*/ return false; } /*}}}*/ +std::vector debSystem::SupportedArchitectures() /*{{{*/ +{ + std::vector archs; + { + string const arch = _config->Find("APT::Architecture"); + if (arch.empty() == false) + archs.push_back(std::move(arch)); + } + + std::vector sArgs = GetDpkgBaseCommand(); + sArgs.push_back("--print-foreign-architectures"); + int outputFd = -1; + pid_t const dpkgMultiArch = ExecDpkg(sArgs, nullptr, &outputFd, true); + if (dpkgMultiArch == -1) + return archs; + + FILE *dpkg = fdopen(outputFd, "r"); + if(dpkg != NULL) { + char* buf = NULL; + size_t bufsize = 0; + while (getline(&buf, &bufsize, dpkg) != -1) + { + char* tok_saveptr; + char* arch = strtok_r(buf, " ", &tok_saveptr); + while (arch != NULL) { + for (; isspace_ascii(*arch) != 0; ++arch); + if (arch[0] != '\0') { + char const* archend = arch; + for (; isspace_ascii(*archend) == 0 && *archend != '\0'; ++archend); + string a(arch, (archend - arch)); + if (std::find(archs.begin(), archs.end(), a) == archs.end()) + archs.push_back(a); + } + arch = strtok_r(NULL, " ", &tok_saveptr); + } + } + free(buf); + fclose(dpkg); + } + ExecWait(dpkgMultiArch, "dpkg --print-foreign-architectures", true); + return archs; +} + /*}}}*/