X-Git-Url: https://git.saurik.com/apt.git/blobdiff_plain/0418949ebe9fc886e7794fa1de17c8b6c74e65ea..20a2b201389092a17763b703039b2e4528234e30:/apt-pkg/contrib/configuration.cc

diff --git a/apt-pkg/contrib/configuration.cc b/apt-pkg/contrib/configuration.cc
index 0949ec223..4de17e3e1 100644
--- a/apt-pkg/contrib/configuration.cc
+++ b/apt-pkg/contrib/configuration.cc
@@ -171,42 +171,60 @@ string Configuration::Find(const char *Name,const char *Default) const
 string Configuration::FindFile(const char *Name,const char *Default) const
 {
    const Item *RootItem = Lookup("RootDir");
-   std::string rootDir =  (RootItem == 0) ? "" : RootItem->Value;
-   if(rootDir.size() > 0 && rootDir[rootDir.size() - 1] != '/')
-     rootDir.push_back('/');
+   std::string result =  (RootItem == 0) ? "" : RootItem->Value;
+   if(result.empty() == false && result[result.size() - 1] != '/')
+     result.push_back('/');
 
    const Item *Itm = Lookup(Name);
    if (Itm == 0 || Itm->Value.empty() == true)
    {
-      if (Default == 0)
-	 return rootDir;
-      else
-	 return rootDir + Default;
+      if (Default != 0)
+	 result.append(Default);
    }
-   
-   string val = Itm->Value;
-   while (Itm->Parent != 0 && Itm->Parent->Value.empty() == false)
-   {	 
-      // Absolute
-      if (val.length() >= 1 && val[0] == '/')
-         break;
-
-      // ~/foo or ./foo 
-      if (val.length() >= 2 && (val[0] == '~' || val[0] == '.') && val[1] == '/')
-	 break;
-	 
-      // ../foo 
-      if (val.length() >= 3 && val[0] == '.' && val[1] == '.' && val[2] == '/')
-	 break;
-      
-      if (Itm->Parent->Value.end()[-1] != '/')
-	 val.insert(0, "/");
+   else
+   {
+      string val = Itm->Value;
+      while (Itm->Parent != 0)
+      {
+	 if (Itm->Parent->Value.empty() == true)
+	 {
+	    Itm = Itm->Parent;
+	    continue;
+	 }
+
+	 // Absolute
+	 if (val.length() >= 1 && val[0] == '/')
+	 {
+	    if (val.compare(0, 9, "/dev/null") == 0)
+	       val.erase(9);
+	    break;
+	 }
+
+	 // ~/foo or ./foo
+	 if (val.length() >= 2 && (val[0] == '~' || val[0] == '.') && val[1] == '/')
+	    break;
+
+	 // ../foo
+	 if (val.length() >= 3 && val[0] == '.' && val[1] == '.' && val[2] == '/')
+	    break;
+
+	 if (Itm->Parent->Value.end()[-1] != '/')
+	    val.insert(0, "/");
 
-      val.insert(0, Itm->Parent->Value);
-      Itm = Itm->Parent;
+	 val.insert(0, Itm->Parent->Value);
+	 Itm = Itm->Parent;
+      }
+      result.append(val);
    }
 
-   return rootDir + val;
+   // do some normalisation by removing // and /./ from the path
+   size_t found = string::npos;
+   while ((found = result.find("/./")) != string::npos)
+      result.replace(found, 3, "/");
+   while ((found = result.find("//")) != string::npos)
+      result.replace(found, 2, "/");
+
+   return result;
 }
 									/*}}}*/
 // Configuration::FindDir - Find a directory name			/*{{{*/
@@ -216,7 +234,12 @@ string Configuration::FindDir(const char *Name,const char *Default) const
 {
    string Res = FindFile(Name,Default);
    if (Res.end()[-1] != '/')
+   {
+      size_t const found = Res.rfind("/dev/null");
+      if (found != string::npos && found == Res.size() - 9)
+	 return Res; // /dev/null returning
       return Res + '/';
+   }
    return Res;
 }
 									/*}}}*/
@@ -476,24 +499,80 @@ bool Configuration::ExistsAny(const char *Name) const
 /* Dump the entire configuration space */
 void Configuration::Dump(ostream& str)
 {
-   /* Write out all of the configuration directives by walking the 
+   Dump(str, NULL, "%f \"%v\";\n", true);
+}
+void Configuration::Dump(ostream& str, char const * const root,
+			 char const * const formatstr, bool const emptyValue)
+{
+   const Configuration::Item* Top = Tree(root);
+   if (Top == 0)
+      return;
+   const Configuration::Item* const Root = (root == NULL) ? NULL : Top;
+   std::vector<std::string> const format = VectorizeString(formatstr, '%');
+
+   /* Write out all of the configuration directives by walking the
       configuration tree */
-   const Configuration::Item *Top = Tree(0);
-   for (; Top != 0;)
-   {
-      str << Top->FullTag() << " \"" << Top->Value << "\";" << endl;
-      
+   do {
+      if (emptyValue == true || Top->Value.empty() == emptyValue)
+      {
+	 std::vector<std::string>::const_iterator f = format.begin();
+	 str << *f;
+	 for (++f; f != format.end(); ++f)
+	 {
+	    if (f->empty() == true)
+	    {
+	       ++f;
+	       str << '%' << *f;
+	       continue;
+	    }
+	    char const type = (*f)[0];
+	    if (type == 'f')
+	       str << Top->FullTag();
+	    else if (type == 't')
+	       str << Top->Tag;
+	    else if (type == 'v')
+	       str << Top->Value;
+	    else if (type == 'F')
+	       str << QuoteString(Top->FullTag(), "=\"\n");
+	    else if (type == 'T')
+	       str << QuoteString(Top->Tag, "=\"\n");
+	    else if (type == 'V')
+	       str << QuoteString(Top->Value, "=\"\n");
+	    else if (type == 'n')
+	       str << "\n";
+	    else if (type == 'N')
+	       str << "\t";
+	    else
+	       str << '%' << type;
+	    str << f->c_str() + 1;
+	 }
+      }
+
       if (Top->Child != 0)
       {
 	 Top = Top->Child;
 	 continue;
       }
-      
+
       while (Top != 0 && Top->Next == 0)
 	 Top = Top->Parent;
       if (Top != 0)
 	 Top = Top->Next;
-   }
+
+      if (Root != NULL)
+      {
+	 const Configuration::Item* I = Top;
+	 while(I != 0)
+	 {
+	    if (I == Root)
+	       break;
+	    else
+	       I = I->Parent;
+	 }
+	 if (I == 0)
+	    break;
+      }
+   } while (Top != 0);
 }
 									/*}}}*/