X-Git-Url: https://git.saurik.com/apt.git/blobdiff_plain/57722714255118560c98b3245413ff5f693b993c..c307a4f0aa29c9c52a0e028524d21b448a53d09b:/apt-pkg/sourcelist.cc?ds=sidebyside

diff --git a/apt-pkg/sourcelist.cc b/apt-pkg/sourcelist.cc
index 47a08ad90..0fddfb451 100644
--- a/apt-pkg/sourcelist.cc
+++ b/apt-pkg/sourcelist.cc
@@ -8,22 +8,19 @@
    ##################################################################### */
 									/*}}}*/
 // Include Files							/*{{{*/
+#include<config.h>
+
 #include <apt-pkg/sourcelist.h>
 #include <apt-pkg/error.h>
 #include <apt-pkg/fileutl.h>
 #include <apt-pkg/strutl.h>
 #include <apt-pkg/configuration.h>
-
-#include <apti18n.h>
+#include <apt-pkg/metaindex.h>
+#include <apt-pkg/indexfile.h>
 
 #include <fstream>
 
-// CNC:2003-03-03 - This is needed for ReadDir stuff.
-#include <algorithm>
-#include <stdio.h>
-#include <dirent.h>
-#include <sys/stat.h>
-#include <unistd.h>
+#include <apti18n.h>
 									/*}}}*/
 
 using namespace std;
@@ -36,7 +33,7 @@ unsigned long pkgSourceList::Type::GlobalListLen = 0;
 // Type::Type - Constructor						/*{{{*/
 // ---------------------------------------------------------------------
 /* Link this to the global list of items*/
-pkgSourceList::Type::Type()
+pkgSourceList::Type::Type() : Name(NULL), Label(NULL)
 {
    ItmList[GlobalListLen] = this;
    GlobalListLen++;
@@ -79,13 +76,58 @@ bool pkgSourceList::Type::FixupURI(string &URI) const
    Weird types may override this. */
 bool pkgSourceList::Type::ParseLine(vector<metaIndex *> &List,
 				    const char *Buffer,
-				    unsigned long CurLine,
-				    string File) const
+				    unsigned long const &CurLine,
+				    string const &File) const
 {
+   for (;Buffer != 0 && isspace(*Buffer); ++Buffer); // Skip whitespaces
+
+   // Parse option field if it exists
+   // e.g.: [ option1=value1 option2=value2 ]
+   map<string, string> Options;
+   if (Buffer != 0 && Buffer[0] == '[')
+   {
+      ++Buffer; // ignore the [
+      for (;Buffer != 0 && isspace(*Buffer); ++Buffer); // Skip whitespaces
+      while (*Buffer != ']')
+      {
+	 // get one option, e.g. option1=value1
+	 string option;
+	 if (ParseQuoteWord(Buffer,option) == false)
+	    return _error->Error(_("Malformed line %lu in source list %s ([option] unparseable)"),CurLine,File.c_str());
+
+	 if (option.length() < 3)
+	    return _error->Error(_("Malformed line %lu in source list %s ([option] too short)"),CurLine,File.c_str());
+
+	 // accept options even if the last has no space before the ]-end marker
+	 if (option.at(option.length()-1) == ']')
+	 {
+	    for (; *Buffer != ']'; --Buffer);
+	    option.resize(option.length()-1);
+	 }
+
+	 size_t const needle = option.find('=');
+	 if (needle == string::npos)
+	    return _error->Error(_("Malformed line %lu in source list %s ([%s] is not an assignment)"),CurLine,File.c_str(), option.c_str());
+
+	 string const key = string(option, 0, needle);
+	 string const value = string(option, needle + 1, option.length());
+
+	 if (key.empty() == true)
+	    return _error->Error(_("Malformed line %lu in source list %s ([%s] has no key)"),CurLine,File.c_str(), option.c_str());
+
+	 if (value.empty() == true)
+	    return _error->Error(_("Malformed line %lu in source list %s ([%s] key %s has no value)"),CurLine,File.c_str(),option.c_str(),key.c_str());
+
+	 Options[key] = value;
+      }
+      ++Buffer; // ignore the ]
+      for (;Buffer != 0 && isspace(*Buffer); ++Buffer); // Skip whitespaces
+   }
+
    string URI;
    string Dist;
-   string Section;   
-   
+   string Section;
+
    if (ParseQuoteWord(Buffer,URI) == false)
       return _error->Error(_("Malformed line %lu in source list %s (URI)"),CurLine,File.c_str());
    if (ParseQuoteWord(Buffer,Dist) == false)
@@ -100,7 +142,7 @@ bool pkgSourceList::Type::ParseLine(vector<metaIndex *> &List,
       if (ParseQuoteWord(Buffer,Section) == true)
 	 return _error->Error(_("Malformed line %lu in source list %s (absolute dist)"),CurLine,File.c_str());
       Dist = SubstVar(Dist,"$(ARCH)",_config->Find("APT::Architecture"));
-      return CreateItem(List,URI,Dist,Section);
+      return CreateItem(List, URI, Dist, Section, Options);
    }
    
    // Grab the rest of the dists
@@ -109,7 +151,7 @@ bool pkgSourceList::Type::ParseLine(vector<metaIndex *> &List,
    
    do
    {
-      if (CreateItem(List,URI,Dist,Section) == false)
+      if (CreateItem(List, URI, Dist, Section, Options) == false)
 	 return false;
    }
    while (ParseQuoteWord(Buffer,Section) == true);
@@ -135,7 +177,7 @@ pkgSourceList::pkgSourceList(string File)
 /* */
 pkgSourceList::~pkgSourceList()
 {
-   for (const_iterator I = SrcList.begin(); I != SrcList.end(); I++)
+   for (const_iterator I = SrcList.begin(); I != SrcList.end(); ++I)
       delete *I;
 }
 									/*}}}*/
@@ -157,16 +199,19 @@ bool pkgSourceList::ReadMainList()
    // CNC:2003-11-28 - Entries in sources.list have priority over
    //                  entries in sources.list.d.
    string Main = _config->FindFile("Dir::Etc::sourcelist");
-   if (FileExists(Main) == true)
+   string Parts = _config->FindDir("Dir::Etc::sourceparts");
+   
+   if (RealFileExists(Main) == true)
       Res &= ReadAppend(Main);
-   else
-      _error->WarningE("FileExists",_("Unable to read %s"),Main.c_str());
+   else if (DirectoryExists(Parts) == false)
+      // Only warn if there are no sources.list.d.
+      _error->WarningE("DirectoryExists", _("Unable to read %s"), Parts.c_str());
 
-   string Parts = _config->FindDir("Dir::Etc::sourceparts");
-   if (FileExists(Parts) == true)
+   if (DirectoryExists(Parts) == true)
       Res &= ReadSourceDir(Parts);
-   else
-      _error->WarningE("FileExists",_("Unable to read %s"),Parts.c_str());
+   else if (RealFileExists(Main) == false)
+      // Only warn if there is no sources.list file.
+      _error->WarningE("RealFileExists", _("Unable to read %s"), Main.c_str());
 
    return Res;
 }
@@ -177,7 +222,7 @@ bool pkgSourceList::ReadMainList()
 /* */
 void pkgSourceList::Reset()
 {
-   for (const_iterator I = SrcList.begin(); I != SrcList.end(); I++)
+   for (const_iterator I = SrcList.begin(); I != SrcList.end(); ++I)
       delete *I;
    SrcList.erase(SrcList.begin(),SrcList.end());
 }
@@ -225,7 +270,7 @@ bool pkgSourceList::ReadAppend(string File)
       // CNC:2003-02-20 - Do not break if '#' is inside [].
       for (I = Buffer; *I != 0 && *I != '#'; I++)
          if (*I == '[')
-	    for (I++; *I != 0 && *I != ']'; I++);
+	    I = strchr(I + 1, ']');
       *I = 0;
       
       const char *C = _strstrip(Buffer);
@@ -243,36 +288,7 @@ bool pkgSourceList::ReadAppend(string File)
       if (Parse == 0)
 	 return _error->Error(_("Type '%s' is not known on line %u in source list %s"),LineType.c_str(),CurLine,File.c_str());
       
-      // Vendor name specified
-      if (C[0] == '[')
-      {
-	 string VendorID;
-	 
-	 if (ParseQuoteWord(C,VendorID) == false)
-	     return _error->Error(_("Malformed line %u in source list %s (vendor id)"),CurLine,File.c_str());
-
-	 if (VendorID.length() < 2 || VendorID.end()[-1] != ']')
-	     return _error->Error(_("Malformed line %u in source list %s (vendor id)"),CurLine,File.c_str());
-	 VendorID = string(VendorID,1,VendorID.size()-2);
-	 
-// 	 for (vector<const Vendor *>::const_iterator iter = VendorList.begin();
-// 	      iter != VendorList.end(); iter++) 
-// 	 {
-// 	    if ((*iter)->GetVendorID() == VendorID)
-// 	    {
-// 	      if (_config->FindB("Debug::sourceList", false)) 
-// 		std::cerr << "Comparing VendorID \"" << VendorID << "\" with \"" << (*iter)->GetVendorID() << '"' << std::endl;
-// 	       Verifier = *iter;
-// 	       break;
-// 	    }
-// 	 }
-
-// 	 if (Verifier == 0)
-// 	    return _error->Error(_("Unknown vendor ID '%s' in line %u of source list %s"),
-// 				 VendorID.c_str(),CurLine,File.c_str());
-      }
-
-      if (Parse->ParseLine(SrcList,C,CurLine,File) == false)
+      if (Parse->ParseLine(SrcList, C, CurLine, File) == false)
 	 return false;
    }
    return true;
@@ -284,11 +300,11 @@ bool pkgSourceList::ReadAppend(string File)
 bool pkgSourceList::FindIndex(pkgCache::PkgFileIterator File,
 			      pkgIndexFile *&Found) const
 {
-   for (const_iterator I = SrcList.begin(); I != SrcList.end(); I++)
+   for (const_iterator I = SrcList.begin(); I != SrcList.end(); ++I)
    {
       vector<pkgIndexFile *> *Indexes = (*I)->GetIndexFiles();
       for (vector<pkgIndexFile *>::const_iterator J = Indexes->begin();
-	   J != Indexes->end(); J++)
+	   J != Indexes->end(); ++J)
       {
          if ((*J)->FindInCache(*File.Cache()) == File)
          {
@@ -306,7 +322,7 @@ bool pkgSourceList::FindIndex(pkgCache::PkgFileIterator File,
 /* */
 bool pkgSourceList::GetIndexes(pkgAcquire *Owner, bool GetAll) const
 {
-   for (const_iterator I = SrcList.begin(); I != SrcList.end(); I++)
+   for (const_iterator I = SrcList.begin(); I != SrcList.end(); ++I)
       if ((*I)->GetIndexes(Owner,GetAll) == false)
 	 return false;
    return true;
@@ -319,48 +335,36 @@ bool pkgSourceList::GetIndexes(pkgAcquire *Owner, bool GetAll) const
 /* */
 bool pkgSourceList::ReadSourceDir(string Dir)
 {
-   DIR *D = opendir(Dir.c_str());
-   if (D == 0)
-      return _error->Errno("opendir",_("Unable to read %s"),Dir.c_str());
-
-   vector<string> List;
-   
-   for (struct dirent *Ent = readdir(D); Ent != 0; Ent = readdir(D))
-   {
-      if (Ent->d_name[0] == '.')
-	 continue;
-
-      // CNC:2003-12-02 Only accept .list files as valid sourceparts
-      if (flExtension(Ent->d_name) != "list")
-	 continue;
-      
-      // Skip bad file names ala run-parts
-      const char *C = Ent->d_name;
-      for (; *C != 0; C++)
-	 if (isalpha(*C) == 0 && isdigit(*C) == 0
-             && *C != '_' && *C != '-' && *C != '.')
-	    break;
-      if (*C != 0)
-	 continue;
-      
-      // Make sure it is a file and not something else
-      string File = flCombine(Dir,Ent->d_name);
-      struct stat St;
-      if (stat(File.c_str(),&St) != 0 || S_ISREG(St.st_mode) == 0)
-	 continue;
-      
-      List.push_back(File);      
-   }   
-   closedir(D);
-   
-   sort(List.begin(),List.end());
+   vector<string> const List = GetListOfFilesInDir(Dir, "list", true);
 
    // Read the files
-   for (vector<string>::const_iterator I = List.begin(); I != List.end(); I++)
+   for (vector<string>::const_iterator I = List.begin(); I != List.end(); ++I)
       if (ReadAppend(*I) == false)
 	 return false;
    return true;
 
 }
 									/*}}}*/
+// GetLastModified()						/*{{{*/
+// ---------------------------------------------------------------------
+/* */
+time_t pkgSourceList::GetLastModifiedTime()
+{
+   vector<string> List;
+
+   string Main = _config->FindFile("Dir::Etc::sourcelist");
+   string Parts = _config->FindDir("Dir::Etc::sourceparts");
+
+   // go over the parts
+   if (DirectoryExists(Parts) == true)
+      List = GetListOfFilesInDir(Parts, "list", true);
+
+   // calculate the time
+   time_t mtime_sources = GetModificationTime(Main);
+   for (vector<string>::const_iterator I = List.begin(); I != List.end(); ++I)
+      mtime_sources = std::max(mtime_sources, GetModificationTime(*I));
+
+   return mtime_sources;
+}
+									/*}}}*/