Просмотр исходного кода

implement a public pkgSystem::ArchitecturesSupported

David Kalnischkies лет назад: 10
Родитель
Сommit
825db89094
5 измененных файлов с 82 добавлено и 83 удалено
  1. 3 82
      apt-pkg/aptconfiguration.cc
  2. 61 1
      apt-pkg/deb/debsystem.cc
  3. 1 0
      apt-pkg/deb/debsystem.h
  4. 8 0
      apt-pkg/pkgsystem.cc
  5. 9 0
      apt-pkg/pkgsystem.h

+ 3 - 82
apt-pkg/aptconfiguration.cc

@@ -16,6 +16,7 @@
 #include <apt-pkg/fileutl.h>
 #include <apt-pkg/macros.h>
 #include <apt-pkg/strutl.h>
+#include <apt-pkg/pkgsystem.h>
 
 #include <dirent.h>
 #include <stdio.h>
@@ -320,88 +321,8 @@ std::vector<std::string> const Configuration::getArchitectures(bool const &Cache
 	string const arch = _config->Find("APT::Architecture");
 	archs = _config->FindVector("APT::Architectures");
 
-	if (unlikely(arch.empty() == true))
-		return archs;
-
-	// FIXME: It is a bit unclean to have debian specific code here…
-	if (archs.empty() == true) {
-		archs.push_back(arch);
-
-		// Generate the base argument list for dpkg
-		std::vector<const char *> Args;
-		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());
-
-		// Stick in any custom dpkg options
-		::Configuration::Item const *Opts = _config->Tree("DPkg::Options");
-		if (Opts != 0) {
-			Opts = Opts->Child;
-			for (; Opts != 0; Opts = Opts->Next)
-			{
-				if (Opts->Value.empty() == true)
-					continue;
-				Args.push_back(Opts->Value.c_str());
-			}
-		}
-
-		Args.push_back("--print-foreign-architectures");
-		Args.push_back(NULL);
-
-		int external[2] = {-1, -1};
-		if (pipe(external) != 0)
-		{
-			_error->WarningE("getArchitecture", "Can't create IPC pipe for dpkg --print-foreign-architectures");
-			return archs;
-		}
-
-		pid_t dpkgMultiArch = ExecFork();
-		if (dpkgMultiArch == 0) {
-			close(external[0]);
-			std::string const chrootDir = _config->FindDir("DPkg::Chroot-Directory");
-			int const nullfd = open("/dev/null", O_RDONLY);
-			dup2(nullfd, STDIN_FILENO);
-			dup2(external[1], STDOUT_FILENO);
-			dup2(nullfd, STDERR_FILENO);
-			if (chrootDir != "/" && chroot(chrootDir.c_str()) != 0 && chdir("/") != 0)
-				_error->WarningE("getArchitecture", "Couldn't chroot into %s for dpkg --print-foreign-architectures", chrootDir.c_str());
-			execvp(Args[0], (char**) &Args[0]);
-			_error->WarningE("getArchitecture", "Can't detect foreign architectures supported by dpkg!");
-			_exit(100);
-		}
-		close(external[1]);
-
-		FILE *dpkg = fdopen(external[0], "r");
-		if(dpkg != NULL) {
-			char buf[1024];
-			char *tok_buf;
-			while (fgets(buf, sizeof(buf), dpkg) != NULL) {
-				char* arch = strtok_r(buf, " ", &tok_buf);
-				while (arch != NULL) {
-					for (; isspace(*arch) != 0; ++arch);
-					if (arch[0] != '\0') {
-						char const* archend = arch;
-						for (; isspace(*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_buf);
-				}
-			}
-			fclose(dpkg);
-		}
-		ExecWait(dpkgMultiArch, "dpkg --print-foreign-architectures", true);
-		return archs;
-	}
+	if (archs.empty() == true)
+	   archs = _system->ArchitecturesSupported();
 
 	if (archs.empty() == true ||
 	    std::find(archs.begin(), archs.end(), arch) == archs.end())

+ 61 - 1
apt-pkg/deb/debsystem.cc

@@ -304,7 +304,6 @@ void debSystem::DpkgChrootDirectory()					/*{{{*/
 									/*}}}*/
 bool debSystem::SupportsMultiArch()					/*{{{*/
 {
-   // Generate the base argument list for dpkg
    std::vector<std::string> const Args = GetDpkgBaseCommand();
    std::vector<const char *> cArgs(Args.size(), NULL);
    std::transform(Args.begin(), Args.end(), cArgs.begin(), [](std::string const &s) { return s.c_str(); });
@@ -343,3 +342,64 @@ bool debSystem::SupportsMultiArch()					/*{{{*/
    return false;
 }
 									/*}}}*/
+std::vector<std::string> debSystem::SupportedArchitectures()		/*{{{*/
+{
+   std::vector<std::string> const sArgs = GetDpkgBaseCommand();
+   std::vector<const char *> 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<std::string> 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;
+   }
+
+   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]);
+
+   FILE *dpkg = fdopen(external[0], "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(*arch) != 0; ++arch);
+	    if (arch[0] != '\0') {
+	       char const* archend = arch;
+	       for (; isspace(*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;
+}
+									/*}}}*/

+ 1 - 0
apt-pkg/deb/debsystem.h

@@ -50,6 +50,7 @@ class debSystem : public pkgSystem
    APT_HIDDEN static std::vector<std::string> GetDpkgBaseCommand();
    APT_HIDDEN static void DpkgChrootDirectory();
    APT_HIDDEN static bool SupportsMultiArch();
+   APT_HIDDEN static std::vector<std::string> SupportedArchitectures();
 };
 
 extern debSystem debSys;

+ 8 - 0
apt-pkg/pkgsystem.cc

@@ -55,5 +55,13 @@ bool pkgSystem::MultiArchSupported() const				/*{{{*/
    return true;
 }
 									/*}}}*/
+std::vector<std::string> pkgSystem::ArchitecturesSupported() const	/*{{{*/
+{
+   debSystem const * const deb = dynamic_cast<debSystem const *>(this);
+   if (deb != NULL)
+      return deb->SupportedArchitectures();
+   return {};
+}
+									/*}}}*/
 
 pkgSystem::~pkgSystem() {}

+ 9 - 0
apt-pkg/pkgsystem.h

@@ -104,6 +104,15 @@ class pkgSystem
     * @return \b true if the system supports MultiArch, \b false if not.
     */
    bool MultiArchSupported() const;
+   /** architectures supported by this system
+    *
+    * A MultiArch capable system might be configured to use
+    * this capability.
+    *
+    * @return a list of all architectures (native + foreign) configured
+    * for on this system (aka: which can be installed without force)
+    */
+   std::vector<std::string> ArchitecturesSupported() const;
 
    pkgSystem(char const * const Label, pkgVersioningSystem * const VS);
    virtual ~pkgSystem();