X-Git-Url: https://git.saurik.com/apt.git/blobdiff_plain/e6ee75afbd4277df7bb2f5dc9ea03c18aecd3986..49e1672884bf8d50713812bdd4eca26ab2076711:/apt-pkg/deb/dpkgpm.cc diff --git a/apt-pkg/deb/dpkgpm.cc b/apt-pkg/deb/dpkgpm.cc index 4c473c1c2..fb0473535 100644 --- a/apt-pkg/deb/dpkgpm.cc +++ b/apt-pkg/deb/dpkgpm.cc @@ -51,8 +51,10 @@ using namespace std; class pkgDPkgPMPrivate { public: - pkgDPkgPMPrivate() : dpkgbuf_pos(0), term_out(NULL), history_out(NULL) + pkgDPkgPMPrivate() : stdin_is_dev_null(false), dpkgbuf_pos(0), + term_out(NULL), history_out(NULL) { + dpkgbuf[0] = '\0'; } bool stdin_is_dev_null; // the buffer we use for the dpkg status-fd reading @@ -135,6 +137,33 @@ static void dpkgChrootDirectory() } /*}}}*/ + +// FindNowVersion - Helper to find a Version in "now" state /*{{{*/ +// --------------------------------------------------------------------- +/* This is helpful when a package is no longer installed but has residual + * config files + */ +static +pkgCache::VerIterator FindNowVersion(const pkgCache::PkgIterator &Pkg) +{ + pkgCache::VerIterator Ver; + for (Ver = Pkg.VersionList(); Ver.end() == false; ++Ver) + { + pkgCache::VerFileIterator Vf = Ver.FileList(); + pkgCache::PkgFileIterator F = Vf.File(); + for (F = Vf.File(); F.end() == false; ++F) + { + if (F && F.Archive()) + { + if (strcmp(F.Archive(), "now")) + return Ver; + } + } + } + return Ver; +} + /*}}}*/ + // DPkgPM::pkgDPkgPM - Constructor /*{{{*/ // --------------------------------------------------------------------- /* */ @@ -158,7 +187,7 @@ pkgDPkgPM::~pkgDPkgPM() bool pkgDPkgPM::Install(PkgIterator Pkg,string File) { if (File.empty() == true || Pkg.end() == true) - return _error->Error("Internal Error, No file name for %s",Pkg.Name()); + return _error->Error("Internal Error, No file name for %s",Pkg.FullName().c_str()); // If the filename string begins with DPkg::Chroot-Directory, return the // substr that is within the chroot so dpkg can access it. @@ -209,15 +238,23 @@ bool pkgDPkgPM::Remove(PkgIterator Pkg,bool Purge) return true; } /*}}}*/ -// DPkgPM::SendV2Pkgs - Send version 2 package info /*{{{*/ +// DPkgPM::SendPkgInfo - Send info for install-pkgs hook /*{{{*/ // --------------------------------------------------------------------- /* This is part of the helper script communication interface, it sends very complete information down to the other end of the pipe.*/ bool pkgDPkgPM::SendV2Pkgs(FILE *F) { - fprintf(F,"VERSION 2\n"); - - /* Write out all of the configuration directives by walking the + return SendPkgsInfo(F, 2); +} +bool pkgDPkgPM::SendPkgsInfo(FILE * const F, unsigned int const &Version) +{ + // This version of APT supports only v3, so don't sent higher versions + if (Version <= 3) + fprintf(F,"VERSION %u\n", Version); + else + fprintf(F,"VERSION 3\n"); + + /* Write out all of the configuration directives by walking the configuration tree */ const Configuration::Item *Top = _config->Tree(0); for (; Top != 0;) @@ -251,30 +288,51 @@ bool pkgDPkgPM::SendV2Pkgs(FILE *F) pkgDepCache::StateCache &S = Cache[I->Pkg]; fprintf(F,"%s ",I->Pkg.Name()); - // Current version - if (I->Pkg->CurrentVer == 0) - fprintf(F,"- "); + + // Current version which we are going to replace + pkgCache::VerIterator CurVer = I->Pkg.CurrentVer(); + if (CurVer.end() == true && (I->Op == Item::Remove || I->Op == Item::Purge)) + CurVer = FindNowVersion(I->Pkg); + + else if (CurVer.end() == true) + { + if (Version <= 2) + fprintf(F, "- "); + else + fprintf(F, "- - none "); + } else - fprintf(F,"%s ",I->Pkg.CurrentVer().VerStr()); - - // Show the compare operator - // Target version + { + fprintf(F, "%s ", CurVer.VerStr()); + if (Version >= 3) + fprintf(F, "%s %s ", CurVer.Arch(), CurVer.MultiArchType()); + } + + // Show the compare operator between current and install version if (S.InstallVer != 0) { + pkgCache::VerIterator const InstVer = S.InstVerIter(Cache); int Comp = 2; - if (I->Pkg->CurrentVer != 0) - Comp = S.InstVerIter(Cache).CompareVer(I->Pkg.CurrentVer()); + if (CurVer.end() == false) + Comp = InstVer.CompareVer(CurVer); if (Comp < 0) fprintf(F,"> "); - if (Comp == 0) + else if (Comp == 0) fprintf(F,"= "); - if (Comp > 0) + else if (Comp > 0) fprintf(F,"< "); - fprintf(F,"%s ",S.InstVerIter(Cache).VerStr()); + fprintf(F, "%s ", InstVer.VerStr()); + if (Version >= 3) + fprintf(F, "%s %s ", InstVer.Arch(), InstVer.MultiArchType()); } else - fprintf(F,"> - "); - + { + if (Version <= 2) + fprintf(F, "> - "); + else + fprintf(F, "> - - none "); + } + // Show the filename/operation if (I->Op == Item::Install) { @@ -284,9 +342,9 @@ bool pkgDPkgPM::SendV2Pkgs(FILE *F) else fprintf(F,"%s\n",I->File.c_str()); } - if (I->Op == Item::Configure) + else if (I->Op == Item::Configure) fprintf(F,"**CONFIGURE**\n"); - if (I->Op == Item::Remove || + else if (I->Op == Item::Remove || I->Op == Item::Purge) fprintf(F,"**REMOVE**\n"); @@ -375,7 +433,7 @@ bool pkgDPkgPM::RunScriptsWithPkgs(const char *Cnf) } } else - SendV2Pkgs(F); + SendPkgsInfo(F, Version); fclose(F); @@ -396,7 +454,7 @@ void pkgDPkgPM::DoStdin(int master) unsigned char input_buf[256] = {0,}; ssize_t len = read(0, input_buf, sizeof(input_buf)); if (len) - write(master, input_buf, len); + FileFd::Write(master, input_buf, len); else d->stdin_is_dev_null = true; } @@ -422,7 +480,7 @@ void pkgDPkgPM::DoTerminalPty(int master) } if(len <= 0) return; - write(1, term_buf, len); + FileFd::Write(1, term_buf, len); if(d->term_out) fwrite(term_buf, len, sizeof(char), d->term_out); } @@ -497,7 +555,7 @@ void pkgDPkgPM::ProcessDpkgStatusLine(int OutStatusFd, char *line) << ":" << s << endl; if(OutStatusFd > 0) - write(OutStatusFd, status.str().c_str(), status.str().size()); + FileFd::Write(OutStatusFd, status.str().c_str(), status.str().size()); if (Debug == true) std::clog << "send: '" << status.str() << "'" << endl; @@ -521,7 +579,7 @@ void pkgDPkgPM::ProcessDpkgStatusLine(int OutStatusFd, char *line) << ":" << list[3] << endl; if(OutStatusFd > 0) - write(OutStatusFd, status.str().c_str(), status.str().size()); + FileFd::Write(OutStatusFd, status.str().c_str(), status.str().size()); if (Debug == true) std::clog << "send: '" << status.str() << "'" << endl; pkgFailures++; @@ -535,7 +593,7 @@ void pkgDPkgPM::ProcessDpkgStatusLine(int OutStatusFd, char *line) << ":" << list[3] << endl; if(OutStatusFd > 0) - write(OutStatusFd, status.str().c_str(), status.str().size()); + FileFd::Write(OutStatusFd, status.str().c_str(), status.str().size()); if (Debug == true) std::clog << "send: '" << status.str() << "'" << endl; return; @@ -563,7 +621,7 @@ void pkgDPkgPM::ProcessDpkgStatusLine(int OutStatusFd, char *line) << ":" << s << endl; if(OutStatusFd > 0) - write(OutStatusFd, status.str().c_str(), status.str().size()); + FileFd::Write(OutStatusFd, status.str().c_str(), status.str().size()); if (Debug == true) std::clog << "send: '" << status.str() << "'" << endl; } @@ -697,7 +755,7 @@ bool pkgDPkgPM::OpenLog() gr = getgrnam("adm"); if (pw != NULL && gr != NULL) chown(logfile_name.c_str(), pw->pw_uid, gr->gr_gid); - chmod(logfile_name.c_str(), 0644); + chmod(logfile_name.c_str(), 0640); fprintf(d->term_out, "\nLog started: %s\n", timestr); } @@ -709,6 +767,7 @@ bool pkgDPkgPM::OpenLog() d->history_out = fopen(history_name.c_str(),"a"); if (d->history_out == NULL) return _error->WarningE("OpenLog", _("Could not open file '%s'"), history_name.c_str()); + SetCloseExec(fileno(d->history_out), true); chmod(history_name.c_str(), 0644); fprintf(d->history_out, "\nStart-Date: %s\n", timestr); string remove, purge, install, reinstall, upgrade, downgrade; @@ -833,10 +892,22 @@ static int racy_pselect(int nfds, fd_set *readfds, fd_set *writefds, */ bool pkgDPkgPM::Go(int OutStatusFd) { + pkgPackageManager::SigINTStop = false; + // Generate the base argument list for dpkg std::vector Args; unsigned long StartSize = 0; - string const Tmp = _config->Find("Dir::Bin::dpkg","dpkg"); + string Tmp = _config->Find("Dir::Bin::dpkg","dpkg"); + { + string const dpkgChrootDir = _config->FindDir("DPkg::Chroot-Directory", "/"); + size_t dpkgChrootLen = dpkgChrootDir.length(); + if (dpkgChrootDir != "/" && Tmp.find(dpkgChrootDir) == 0) + { + if (dpkgChrootDir[dpkgChrootLen - 1] == '/') + --dpkgChrootLen; + Tmp = Tmp.substr(dpkgChrootLen); + } + } Args.push_back(Tmp.c_str()); StartSize += Tmp.length(); @@ -868,7 +939,7 @@ bool pkgDPkgPM::Go(int OutStatusFd) dup2(nullfd, STDIN_FILENO); dup2(nullfd, STDOUT_FILENO); dup2(nullfd, STDERR_FILENO); - execv(Args[0], (char**) &Args[0]); + execvp(Args[0], (char**) &Args[0]); _error->WarningE("dpkgGo", "Can't detect if dpkg supports multi-arch!"); _exit(2); } @@ -1014,7 +1085,8 @@ bool pkgDPkgPM::Go(int OutStatusFd) } int fd[2]; - pipe(fd); + if (pipe(fd) != 0) + return _error->Errno("pipe","Failed to create IPC pipe to dpkg"); #define ADDARG(X) Args.push_back(X); Size += strlen(X) #define ADDARGC(X) Args.push_back(X); Size += sizeof(X) - 1 @@ -1088,7 +1160,9 @@ bool pkgDPkgPM::Go(int OutStatusFd) if (I->Op == Item::Configure && disappearedPkgs.find(I->Pkg.Name()) != disappearedPkgs.end()) continue; // We keep this here to allow "smooth" transitions from e.g. multiarch dpkg/ubuntu to dpkg/debian - if (dpkgMultiArch == false && (I->Pkg.Arch() == nativeArch || !strcmp(I->Pkg.Arch(), "all"))) + if (dpkgMultiArch == false && (I->Pkg.Arch() == nativeArch || + strcmp(I->Pkg.Arch(), "all") == 0 || + strcmp(I->Pkg.Arch(), "none") == 0)) { char const * const name = I->Pkg.Name(); ADDARG(name); @@ -1097,11 +1171,20 @@ bool pkgDPkgPM::Go(int OutStatusFd) { pkgCache::VerIterator PkgVer; std::string name = I->Pkg.Name(); - if (Op == Item::Remove || Op == Item::Purge) + if (Op == Item::Remove || Op == Item::Purge) + { PkgVer = I->Pkg.CurrentVer(); + if(PkgVer.end() == true) + PkgVer = FindNowVersion(I->Pkg); + } else PkgVer = Cache[I->Pkg].InstVerIter(Cache); - name.append(":").append(PkgVer.Arch()); + if (strcmp(I->Pkg.Arch(), "none") == 0) + ; // never arch-qualify a package without an arch + else if (PkgVer.end() == false) + name.append(":").append(PkgVer.Arch()); + else + _error->Warning("Can not find PkgVer for '%s'", name.c_str()); char * const fullname = strdup(name.c_str()); Packages.push_back(fullname); ADDARG(fullname); @@ -1188,7 +1271,7 @@ bool pkgDPkgPM::Go(int OutStatusFd) << (PackagesDone/float(PackagesTotal)*100.0) << ":" << _("Running dpkg") << endl; - write(OutStatusFd, status.str().c_str(), status.str().size()); + FileFd::Write(OutStatusFd, status.str().c_str(), status.str().size()); } Child = ExecFork(); @@ -1385,9 +1468,8 @@ bool pkgDPkgPM::Go(int OutStatusFd) } void SigINT(int sig) { - if (_config->FindB("APT::Immediate-Configure-All",false)) - pkgPackageManager::SigINTStop = true; -} + pkgPackageManager::SigINTStop = true; +} /*}}}*/ // pkgDpkgPM::Reset - Dump the contents of the command list /*{{{*/ // --------------------------------------------------------------------- @@ -1402,6 +1484,12 @@ void pkgDPkgPM::Reset() /* */ void pkgDPkgPM::WriteApportReport(const char *pkgpath, const char *errormsg) { + // If apport doesn't exist or isn't installed do nothing + // This e.g. prevents messages in 'universes' without apport + pkgCache::PkgIterator apportPkg = Cache.FindPkg("apport"); + if (apportPkg.end() == true || apportPkg->CurrentVer == 0) + return; + string pkgname, reportfile, srcpkgname, pkgver, arch; string::size_type pos; FILE *report; @@ -1489,7 +1577,7 @@ void pkgDPkgPM::WriteApportReport(const char *pkgpath, const char *errormsg) if(strstr(strbuf,"Package:") == strbuf) { char pkgname[255], version[255]; - if(sscanf(strbuf, "Package: %s %s", pkgname, version) == 2) + if(sscanf(strbuf, "Package: %254s %254s", pkgname, version) == 2) if(strcmp(pkgver.c_str(), version) == 0) { fclose(report); @@ -1526,12 +1614,12 @@ void pkgDPkgPM::WriteApportReport(const char *pkgpath, const char *errormsg) if (!logfile_name.empty()) { FILE *log = NULL; - char buf[1024]; fprintf(report, "DpkgTerminalLog:\n"); log = fopen(logfile_name.c_str(),"r"); if(log != NULL) { + char buf[1024]; while( fgets(buf, sizeof(buf), log) != NULL) fprintf(report, " %s", buf); fclose(log); @@ -1542,18 +1630,19 @@ void pkgDPkgPM::WriteApportReport(const char *pkgpath, const char *errormsg) const char *ops_str[] = {"Install", "Configure","Remove","Purge"}; fprintf(report, "AptOrdering:\n"); for (vector::iterator I = List.begin(); I != List.end(); ++I) - fprintf(report, " %s: %s\n", (*I).Pkg.Name(), ops_str[(*I).Op]); + if ((*I).Pkg != NULL) + fprintf(report, " %s: %s\n", (*I).Pkg.Name(), ops_str[(*I).Op]); + else + fprintf(report, " %s: %s\n", "NULL", ops_str[(*I).Op]); // attach dmesg log (to learn about segfaults) if (FileExists("/bin/dmesg")) { - FILE *log = NULL; - char buf[1024]; - fprintf(report, "Dmesg:\n"); - log = popen("/bin/dmesg","r"); + FILE *log = popen("/bin/dmesg","r"); if(log != NULL) { + char buf[1024]; while( fgets(buf, sizeof(buf), log) != NULL) fprintf(report, " %s", buf); pclose(log); @@ -1563,13 +1652,12 @@ void pkgDPkgPM::WriteApportReport(const char *pkgpath, const char *errormsg) // attach df -l log (to learn about filesystem status) if (FileExists("/bin/df")) { - FILE *log = NULL; - char buf[1024]; fprintf(report, "Df:\n"); - log = popen("/bin/df -l","r"); + FILE *log = popen("/bin/df -l","r"); if(log != NULL) { + char buf[1024]; while( fgets(buf, sizeof(buf), log) != NULL) fprintf(report, " %s", buf); pclose(log);