]> git.saurik.com Git - apt.git/blobdiff - apt-pkg/contrib/configuration.cc
fileutl: simple_buffer: Add write() and full() methods
[apt.git] / apt-pkg / contrib / configuration.cc
index ff80dfaf870f37b4913b8e08349add6b32ec6ef7..d4bb72a8b61ea606e161163308f008e2941b588b 100644 (file)
 #include <apt-pkg/error.h>
 #include <apt-pkg/strutl.h>
 #include <apt-pkg/fileutl.h>
+#include <apt-pkg/macros.h>
 
+#include <ctype.h>
+#include <regex.h>
+#include <stddef.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <algorithm>
+#include <string>
 #include <vector>
 #include <fstream>
-#include <iostream>
 
 #include <apti18n.h>
 
@@ -42,8 +50,7 @@ Configuration::Configuration() : ToFree(true)
 }
 Configuration::Configuration(const Item *Root) : Root((Item *)Root), ToFree(false)
 {
-};
-
+}
                                                                        /*}}}*/
 // Configuration::~Configuration - Destructor                          /*{{{*/
 // ---------------------------------------------------------------------
@@ -171,48 +178,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)
+   else
    {
-      if (Itm->Parent->Value.empty() == true)
+      string val = Itm->Value;
+      while (Itm->Parent != 0)
       {
-        Itm = Itm->Parent;
-        continue;
-      }
+        if (Itm->Parent->Value.empty() == true)
+        {
+           Itm = Itm->Parent;
+           continue;
+        }
 
-      // Absolute
-      if (val.length() >= 1 && val[0] == '/')
-         break;
+        // 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, "/");
+        // ~/foo or ./foo
+        if (val.length() >= 2 && (val[0] == '~' || val[0] == '.') && val[1] == '/')
+           break;
 
-      val.insert(0, Itm->Parent->Value);
-      Itm = Itm->Parent;
+        // ../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;
+      }
+      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                      /*{{{*/
@@ -222,26 +241,37 @@ 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;
 }
                                                                        /*}}}*/
 // Configuration::FindVector - Find a vector of values                 /*{{{*/
 // ---------------------------------------------------------------------
 /* Returns a vector of config values under the given item */
-vector<string> Configuration::FindVector(const char *Name) const
+vector<string> Configuration::FindVector(const char *Name, std::string const &Default, bool const Keys) const
 {
    vector<string> Vec;
    const Item *Top = Lookup(Name);
    if (Top == NULL)
-      return Vec;
+      return VectorizeString(Default, ',');
+
+   if (Top->Value.empty() == false)
+      return VectorizeString(Top->Value, ',');
 
    Item *I = Top->Child;
    while(I != NULL)
    {
-      Vec.push_back(I->Value);
+      Vec.push_back(Keys ? I->Tag : I->Value);
       I = I->Next;
    }
+   if (Vec.empty() == true)
+      return VectorizeString(Default, ',');
+
    return Vec;
 }
                                                                        /*}}}*/
@@ -403,6 +433,18 @@ void Configuration::Clear(string const &Name, string const &Value)
       }
    }
      
+}
+                                                                       /*}}}*/
+// Configuration::Clear - Clear everything                             /*{{{*/
+// ---------------------------------------------------------------------
+void Configuration::Clear()
+{
+   const Configuration::Item *Top = Tree(0);
+   while( Top != 0 )
+   {
+      Clear(Top->FullTag());
+      Top = Top->Next;
+   }
 }
                                                                        /*}}}*/
 // Configuration::Clear - Clear an entire tree                         /*{{{*/
@@ -443,6 +485,59 @@ void Configuration::Clear(string const &Name)
    }
 }
                                                                        /*}}}*/
+void Configuration::MoveSubTree(char const * const OldRootName, char const * const NewRootName)/*{{{*/
+{
+   // prevent NewRoot being a subtree of OldRoot
+   if (OldRootName == nullptr)
+      return;
+   if (NewRootName != nullptr)
+   {
+      if (strcmp(OldRootName, NewRootName) == 0)
+        return;
+      std::string const oldroot = std::string(OldRootName) + "::";
+      if (strcasestr(NewRootName, oldroot.c_str()) != NULL)
+        return;
+   }
+
+   Item * Top;
+   Item const * const OldRoot = Top = Lookup(OldRootName, false);
+   if (Top == nullptr)
+      return;
+   std::string NewRoot;
+   if (NewRootName != nullptr)
+      NewRoot.append(NewRootName).append("::");
+
+   Top->Value.clear();
+   Item * const Stop = Top;
+   Top = Top->Child;
+   Stop->Child = 0;
+   for (; Top != 0;)
+   {
+      if (Top->Child != 0)
+      {
+        Top = Top->Child;
+        continue;
+      }
+
+      while (Top != 0 && Top->Next == 0)
+      {
+        Set(NewRoot + Top->FullTag(OldRoot), Top->Value);
+        Item const * const Tmp = Top;
+        Top = Top->Parent;
+        delete Tmp;
+
+        if (Top == Stop)
+           return;
+      }
+
+      Set(NewRoot + Top->FullTag(OldRoot), Top->Value);
+      Item const * const Tmp = Top;
+      if (Top != 0)
+        Top = Top->Next;
+      delete Tmp;
+   }
+}
+                                                                       /*}}}*/
 // Configuration::Exists - Returns true if the Name exists             /*{{{*/
 // ---------------------------------------------------------------------
 /* */
@@ -581,19 +676,19 @@ string Configuration::Item::FullTag(const Item *Stop) const
    tag/value. AsSectional enables Sectional parsing.*/
 bool ReadConfigFile(Configuration &Conf,const string &FName,bool const &AsSectional,
                    unsigned const &Depth)
-{   
+{
    // Open the stream for reading
-   ifstream F(FName.c_str(),ios::in); 
-   if (!F != 0)
+   ifstream F(FName.c_str(),ios::in);
+   if (F.fail() == true)
       return _error->Errno("ifstream::ifstream",_("Opening configuration file %s"),FName.c_str());
 
    string LineBuffer;
    string Stack[100];
    unsigned int StackPos = 0;
-   
+
    // Parser state
    string ParentTag;
-   
+
    int CurLine = 0;
    bool InComment = false;
    while (F.eof() == false)
@@ -794,7 +889,7 @@ bool ReadConfigFile(Configuration &Conf,const string &FName,bool const &AsSectio
            // Go down a level
            if (TermChar == '{')
            {
-              if (StackPos <= 100)
+              if (StackPos < sizeof(Stack)/sizeof(std::string))
                  Stack[StackPos++] = ParentTag;
               
               /* Make sectional tags incorperate the section into the
@@ -941,7 +1036,7 @@ Configuration::MatchAgainstConfig::MatchAgainstConfig(char const * Config)
         continue;
       }
    }
-   if (strings.size() == 0)
+   if (strings.empty() == true)
       patterns.push_back(NULL);
 }
                                                                        /*}}}*/