]>
git.saurik.com Git - apt.git/blob - apt-pkg/sourcelist.cc
   1 // -*- mode: cpp; mode: fold -*- 
   3 // $Id: sourcelist.cc,v 1.3 2002/08/15 20:51:37 niemeyer Exp $ 
   4 /* ###################################################################### 
   8    ##################################################################### */ 
  10 // Include Files                                                        /*{{{*/ 
  13 #include <apt-pkg/sourcelist.h> 
  14 #include <apt-pkg/error.h> 
  15 #include <apt-pkg/fileutl.h> 
  16 #include <apt-pkg/strutl.h> 
  17 #include <apt-pkg/configuration.h> 
  18 #include <apt-pkg/metaindex.h> 
  19 #include <apt-pkg/indexfile.h> 
  28 // Global list of Items supported 
  29 static  pkgSourceList::Type 
*ItmList
[10]; 
  30 pkgSourceList::Type 
**pkgSourceList::Type::GlobalList 
= ItmList
; 
  31 unsigned long pkgSourceList::Type::GlobalListLen 
= 0; 
  33 // Type::Type - Constructor                                             /*{{{*/ 
  34 // --------------------------------------------------------------------- 
  35 /* Link this to the global list of items*/ 
  36 pkgSourceList::Type::Type() 
  38    ItmList
[GlobalListLen
] = this; 
  42 // Type::GetType - Get a specific meta for a given type                 /*{{{*/ 
  43 // --------------------------------------------------------------------- 
  45 pkgSourceList::Type 
*pkgSourceList::Type::GetType(const char *Type
) 
  47    for (unsigned I 
= 0; I 
!= GlobalListLen
; I
++) 
  48       if (strcmp(GlobalList
[I
]->Name
,Type
) == 0) 
  53 // Type::FixupURI - Normalize the URI and check it..                    /*{{{*/ 
  54 // --------------------------------------------------------------------- 
  56 bool pkgSourceList::Type::FixupURI(string 
&URI
) const 
  58    if (URI
.empty() == true) 
  61    if (URI
.find(':') == string::npos
) 
  64    URI 
= SubstVar(URI
,"$(ARCH)",_config
->Find("APT::Architecture")); 
  66    // Make sure that the URI is / postfixed 
  67    if (URI
[URI
.size() - 1] != '/') 
  73 // Type::ParseLine - Parse a single line                                /*{{{*/ 
  74 // --------------------------------------------------------------------- 
  75 /* This is a generic one that is the 'usual' format for sources.list 
  76    Weird types may override this. */ 
  77 bool pkgSourceList::Type::ParseLine(vector
<metaIndex 
*> &List
, 
  79                                     unsigned long const &CurLine
, 
  80                                     string 
const &File
) const 
  82    for (;Buffer 
!= 0 && isspace(*Buffer
); ++Buffer
); // Skip whitespaces 
  84    // Parse option field if it exists 
  85    // e.g.: [ option1=value1 option2=value2 ] 
  86    map
<string
, string
> Options
; 
  87    if (Buffer 
!= 0 && Buffer
[0] == '[') 
  89       ++Buffer
; // ignore the [ 
  90       for (;Buffer 
!= 0 && isspace(*Buffer
); ++Buffer
); // Skip whitespaces 
  91       while (*Buffer 
!= ']') 
  93          // get one option, e.g. option1=value1 
  95          if (ParseQuoteWord(Buffer
,option
) == false) 
  96             return _error
->Error(_("Malformed line %lu in source list %s ([option] unparseable)"),CurLine
,File
.c_str()); 
  98          if (option
.length() < 3) 
  99             return _error
->Error(_("Malformed line %lu in source list %s ([option] too short)"),CurLine
,File
.c_str()); 
 101          // accept options even if the last has no space before the ]-end marker 
 102          if (option
.at(option
.length()-1) == ']') 
 104             for (; *Buffer 
!= ']'; --Buffer
); 
 105             option
.resize(option
.length()-1); 
 108          size_t const needle 
= option
.find('='); 
 109          if (needle 
== string::npos
) 
 110             return _error
->Error(_("Malformed line %lu in source list %s ([%s] is not an assignment)"),CurLine
,File
.c_str(), option
.c_str()); 
 112          string 
const key 
= string(option
, 0, needle
); 
 113          string 
const value 
= string(option
, needle 
+ 1, option
.length()); 
 115          if (key
.empty() == true) 
 116             return _error
->Error(_("Malformed line %lu in source list %s ([%s] has no key)"),CurLine
,File
.c_str(), option
.c_str()); 
 118          if (value
.empty() == true) 
 119             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()); 
 121          Options
[key
] = value
; 
 123       ++Buffer
; // ignore the ] 
 124       for (;Buffer 
!= 0 && isspace(*Buffer
); ++Buffer
); // Skip whitespaces 
 131    if (ParseQuoteWord(Buffer
,URI
) == false) 
 132       return _error
->Error(_("Malformed line %lu in source list %s (URI)"),CurLine
,File
.c_str()); 
 133    if (ParseQuoteWord(Buffer
,Dist
) == false) 
 134       return _error
->Error(_("Malformed line %lu in source list %s (dist)"),CurLine
,File
.c_str()); 
 136    if (FixupURI(URI
) == false) 
 137       return _error
->Error(_("Malformed line %lu in source list %s (URI parse)"),CurLine
,File
.c_str()); 
 139    // Check for an absolute dists specification. 
 140    if (Dist
.empty() == false && Dist
[Dist
.size() - 1] == '/') 
 142       if (ParseQuoteWord(Buffer
,Section
) == true) 
 143          return _error
->Error(_("Malformed line %lu in source list %s (absolute dist)"),CurLine
,File
.c_str()); 
 144       Dist 
= SubstVar(Dist
,"$(ARCH)",_config
->Find("APT::Architecture")); 
 145       return CreateItem(List
, URI
, Dist
, Section
, Options
); 
 148    // Grab the rest of the dists 
 149    if (ParseQuoteWord(Buffer
,Section
) == false) 
 150       return _error
->Error(_("Malformed line %lu in source list %s (dist parse)"),CurLine
,File
.c_str()); 
 154       if (CreateItem(List
, URI
, Dist
, Section
, Options
) == false) 
 157    while (ParseQuoteWord(Buffer
,Section
) == true); 
 163 // SourceList::pkgSourceList - Constructors                             /*{{{*/ 
 164 // --------------------------------------------------------------------- 
 166 pkgSourceList::pkgSourceList() 
 170 pkgSourceList::pkgSourceList(string File
) 
 175 // SourceList::~pkgSourceList - Destructor                              /*{{{*/ 
 176 // --------------------------------------------------------------------- 
 178 pkgSourceList::~pkgSourceList() 
 180    for (const_iterator I 
= SrcList
.begin(); I 
!= SrcList
.end(); ++I
) 
 185 // SourceList::ReadMainList - Read the main source list from etc        /*{{{*/ 
 186 // --------------------------------------------------------------------- 
 188 bool pkgSourceList::ReadMainList() 
 190    // CNC:2003-03-03 - Multiple sources list support. 
 199    // CNC:2003-11-28 - Entries in sources.list have priority over 
 200    //                  entries in sources.list.d. 
 201    string Main 
= _config
->FindFile("Dir::Etc::sourcelist"); 
 202    string Parts 
= _config
->FindDir("Dir::Etc::sourceparts"); 
 204    if (RealFileExists(Main
) == true) 
 205       Res 
&= ReadAppend(Main
); 
 206    else if (DirectoryExists(Parts
) == false) 
 207       // Only warn if there are no sources.list.d. 
 208       _error
->WarningE("DirectoryExists", _("Unable to read %s"), Parts
.c_str()); 
 210    if (DirectoryExists(Parts
) == true) 
 211       Res 
&= ReadSourceDir(Parts
); 
 212    else if (RealFileExists(Main
) == false) 
 213       // Only warn if there is no sources.list file. 
 214       _error
->WarningE("RealFileExists", _("Unable to read %s"), Main
.c_str()); 
 219 // CNC:2003-03-03 - Needed to preserve backwards compatibility. 
 220 // SourceList::Reset - Clear the sourcelist contents                    /*{{{*/ 
 221 // --------------------------------------------------------------------- 
 223 void pkgSourceList::Reset() 
 225    for (const_iterator I 
= SrcList
.begin(); I 
!= SrcList
.end(); ++I
) 
 227    SrcList
.erase(SrcList
.begin(),SrcList
.end()); 
 230 // CNC:2003-03-03 - Function moved to ReadAppend() and Reset(). 
 231 // SourceList::Read - Parse the sourcelist file                         /*{{{*/ 
 232 // --------------------------------------------------------------------- 
 234 bool pkgSourceList::Read(string File
) 
 237    return ReadAppend(File
); 
 240 // SourceList::ReadAppend - Parse a sourcelist file                     /*{{{*/ 
 241 // --------------------------------------------------------------------- 
 243 bool pkgSourceList::ReadAppend(string File
) 
 245    // Open the stream for reading 
 246    ifstream 
F(File
.c_str(),ios::in 
/*| ios::nocreate*/); 
 248       return _error
->Errno("ifstream::ifstream",_("Opening %s"),File
.c_str()); 
 250 #if 0 // Now Reset() does this. 
 251    for (const_iterator I 
= SrcList
.begin(); I 
!= SrcList
.end(); I
++) 
 253    SrcList
.erase(SrcList
.begin(),SrcList
.end()); 
 255    // CNC:2003-12-10 - 300 is too short. 
 259    while (F
.eof() == false) 
 261       F
.getline(Buffer
,sizeof(Buffer
)); 
 263       _strtabexpand(Buffer
,sizeof(Buffer
)); 
 264       if (F
.fail() && !F
.eof()) 
 265          return _error
->Error(_("Line %u too long in source list %s."), 
 266                               CurLine
,File
.c_str()); 
 270       // CNC:2003-02-20 - Do not break if '#' is inside []. 
 271       for (I 
= Buffer
; *I 
!= 0 && *I 
!= '#'; I
++) 
 273             I 
= strchr(I 
+ 1, ']'); 
 276       const char *C 
= _strstrip(Buffer
); 
 279       if (C
[0] == '#' || C
[0] == 0) 
 284       if (ParseQuoteWord(C
,LineType
) == false) 
 285          return _error
->Error(_("Malformed line %u in source list %s (type)"),CurLine
,File
.c_str()); 
 287       Type 
*Parse 
= Type::GetType(LineType
.c_str()); 
 289          return _error
->Error(_("Type '%s' is not known on line %u in source list %s"),LineType
.c_str(),CurLine
,File
.c_str()); 
 291       if (Parse
->ParseLine(SrcList
, C
, CurLine
, File
) == false) 
 297 // SourceList::FindIndex - Get the index associated with a file         /*{{{*/ 
 298 // --------------------------------------------------------------------- 
 300 bool pkgSourceList::FindIndex(pkgCache::PkgFileIterator File
, 
 301                               pkgIndexFile 
*&Found
) const 
 303    for (const_iterator I 
= SrcList
.begin(); I 
!= SrcList
.end(); ++I
) 
 305       vector
<pkgIndexFile 
*> *Indexes 
= (*I
)->GetIndexFiles(); 
 306       for (vector
<pkgIndexFile 
*>::const_iterator J 
= Indexes
->begin(); 
 307            J 
!= Indexes
->end(); ++J
) 
 309          if ((*J
)->FindInCache(*File
.Cache()) == File
) 
 320 // SourceList::GetIndexes - Load the index files into the downloader    /*{{{*/ 
 321 // --------------------------------------------------------------------- 
 323 bool pkgSourceList::GetIndexes(pkgAcquire 
*Owner
, bool GetAll
) const 
 325    for (const_iterator I 
= SrcList
.begin(); I 
!= SrcList
.end(); ++I
) 
 326       if ((*I
)->GetIndexes(Owner
,GetAll
) == false) 
 331 // CNC:2003-03-03 - By Anton V. Denisov <avd@altlinux.org>. 
 332 // SourceList::ReadSourceDir - Read a directory with sources files 
 333 // Based on ReadConfigDir()                                             /*{{{*/ 
 334 // --------------------------------------------------------------------- 
 336 bool pkgSourceList::ReadSourceDir(string Dir
) 
 338    vector
<string
> const List 
= GetListOfFilesInDir(Dir
, "list", true); 
 341    for (vector
<string
>::const_iterator I 
= List
.begin(); I 
!= List
.end(); ++I
) 
 342       if (ReadAppend(*I
) == false) 
 348 // GetLastModified()                                            /*{{{*/ 
 349 // --------------------------------------------------------------------- 
 351 time_t pkgSourceList::GetLastModifiedTime() 
 355    string Main 
= _config
->FindFile("Dir::Etc::sourcelist"); 
 356    string Parts 
= _config
->FindDir("Dir::Etc::sourceparts"); 
 359    if (DirectoryExists(Parts
) == true) 
 360       List 
= GetListOfFilesInDir(Parts
, "list", true); 
 362    // calculate the time 
 363    time_t mtime_sources 
= GetModificationTime(Main
); 
 364    for (vector
<string
>::const_iterator I 
= List
.begin(); I 
!= List
.end(); ++I
) 
 365       mtime_sources 
= std::max(mtime_sources
, GetModificationTime(*I
)); 
 367    return mtime_sources
;