X-Git-Url: https://git.saurik.com/apt.git/blobdiff_plain/825db89094a8413dcc9c8ef3abe0a45b0bb7a2e2..c0723bf1a60daf45096998d4ae9feee3c44343f8:/apt-pkg/deb/debsystem.cc diff --git a/apt-pkg/deb/debsystem.cc b/apt-pkg/deb/debsystem.cc index 724312bc5..899f7328b 100644 --- a/apt-pkg/deb/debsystem.cc +++ b/apt-pkg/deb/debsystem.cc @@ -86,7 +86,7 @@ bool debSystem::Lock() } // Create the lockfile - string AdminDir = flNotFile(_config->Find("Dir::State::status")); + string AdminDir = flNotFile(_config->FindFile("Dir::State::status")); d->LockFD = GetLock(AdminDir + "lock"); if (d->LockFD == -1) { @@ -145,7 +145,7 @@ bool debSystem::UnLock(bool NoErrors) bool debSystem::CheckUpdates() { // Check for updates.. (dirty) - string File = flNotFile(_config->Find("Dir::State::status")) + "updates/"; + string File = flNotFile(_config->FindFile("Dir::State::status")) + "updates/"; DIR *DirP = opendir(File.c_str()); if (DirP == 0) return false; @@ -184,14 +184,34 @@ pkgPackageManager *debSystem::CreatePM(pkgDepCache *Cache) const // System::Initialize - Setup the configuration space.. /*{{{*/ // --------------------------------------------------------------------- /* These are the Debian specific configuration variables.. */ +static std::string getDpkgStatusLocation(Configuration const &Cnf) { + Configuration PathCnf; + PathCnf.Set("Dir", Cnf.Find("Dir", "/")); + PathCnf.Set("Dir::State::status", "status"); + auto const cnfstatedir = Cnf.Find("Dir::State", STATE_DIR + 1); + // if the state dir ends in apt, replace it with dpkg - + // for the default this gives us the same as the fallback below. + // This can't be a ../dpkg as that would play bad with symlinks + std::string statedir; + if (APT::String::Endswith(cnfstatedir, "/apt/")) + statedir.assign(cnfstatedir, 0, cnfstatedir.length() - 5); + else if (APT::String::Endswith(cnfstatedir, "/apt")) + statedir.assign(cnfstatedir, 0, cnfstatedir.length() - 4); + if (statedir.empty()) + PathCnf.Set("Dir::State", "var/lib/dpkg"); + else + PathCnf.Set("Dir::State", flCombine(statedir, "dpkg")); + return PathCnf.FindFile("Dir::State::status"); +} bool debSystem::Initialize(Configuration &Cnf) { /* These really should be jammed into a generic 'Local Database' engine which is yet to be determined. The functions in pkgcachegen should be the only users of these */ Cnf.CndSet("Dir::State::extended_states", "extended_states"); - Cnf.CndSet("Dir::State::status","/var/lib/dpkg/status"); - Cnf.CndSet("Dir::Bin::dpkg","/usr/bin/dpkg"); + if (Cnf.Exists("Dir::State::status") == false) + Cnf.Set("Dir::State::status", getDpkgStatusLocation(Cnf)); + Cnf.CndSet("Dir::Bin::dpkg",BIN_DIR"/dpkg"); if (d->StatusFile) { delete d->StatusFile; @@ -219,9 +239,9 @@ APT_PURE bool debSystem::ArchiveSupported(const char *Type) signed debSystem::Score(Configuration const &Cnf) { signed Score = 0; - if (FileExists(Cnf.FindFile("Dir::State::status","/var/lib/dpkg/status")) == true) + if (FileExists(Cnf.FindFile("Dir::State::status",getDpkgStatusLocation(Cnf).c_str())) == true) Score += 10; - if (FileExists(Cnf.FindFile("Dir::Bin::dpkg","/usr/bin/dpkg")) == true) + if (FileExists(Cnf.Find("Dir::Bin::dpkg",BIN_DIR"/dpkg")) == true) Score += 10; if (FileExists("/etc/debian_version") == true) Score += 10; @@ -302,30 +322,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)/*{{{*/ { - 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; @@ -344,39 +396,21 @@ bool debSystem::SupportsMultiArch() /*{{{*/ /*}}}*/ std::vector debSystem::SupportedArchitectures() /*{{{*/ { - std::vector const sArgs = GetDpkgBaseCommand(); - 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("--print-foreign-architectures"); - Args.push_back(NULL); - std::vector archs; - string const arch = _config->Find("APT::Architecture"); - if (arch.empty() == false) - archs.push_back(arch); - - int external[2] = {-1, -1}; - if (pipe(external) != 0) { - _error->WarningE("getArchitecture", "Can't create IPC pipe for dpkg --print-foreign-architectures"); - return archs; + string const arch = _config->Find("APT::Architecture"); + if (arch.empty() == false) + archs.push_back(std::move(arch)); } - pid_t dpkgMultiArch = ExecFork(); - if (dpkgMultiArch == 0) { - close(external[0]); - int const nullfd = open("/dev/null", O_RDONLY); - dup2(nullfd, STDIN_FILENO); - dup2(external[1], STDOUT_FILENO); - dup2(nullfd, STDERR_FILENO); - DpkgChrootDirectory(); - execvp(Args[0], (char**) &Args[0]); - _error->WarningE("getArchitecture", "Can't detect foreign architectures supported by dpkg!"); - _exit(100); - } - close(external[1]); + 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(external[0], "r"); + FILE *dpkg = fdopen(outputFd, "r"); if(dpkg != NULL) { char* buf = NULL; size_t bufsize = 0; @@ -385,10 +419,10 @@ std::vector debSystem::SupportedArchitectures() /*{{{*/ char* tok_saveptr; char* arch = strtok_r(buf, " ", &tok_saveptr); while (arch != NULL) { - for (; isspace(*arch) != 0; ++arch); + for (; isspace_ascii(*arch) != 0; ++arch); if (arch[0] != '\0') { char const* archend = arch; - for (; isspace(*archend) == 0 && *archend != '\0'; ++archend); + 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);