// -*- mode: cpp; mode: fold -*-
// Description /*{{{*/
-// $Id: strutl.cc,v 1.2 1998/07/16 06:08:41 jgg Exp $
+// $Id: strutl.cc,v 1.3 1998/07/19 04:22:08 jgg Exp $
/* ######################################################################
String Util - Some usefull string functions.
return Temp + string(Str,OldPos);
}
/*}}}*/
+// URItoFileName - Convert the uri into a unique file name /*{{{*/
+// ---------------------------------------------------------------------
+/* This converts a URI into a safe filename. It quotes all unsafe characters
+ and converts / to _ and removes the scheme identifier. The resulting
+ file name should be unique and never occur again for a different file */
+string URItoFileName(string URI)
+{
+ string::const_iterator I = URI.begin() + URI.find(':') + 1;
+ for (; I < URI.end() && *I == '/'; I++);
+
+ // "\x00-\x20{}|\\\\^\\[\\]<>\"\x7F-\xFF";
+ URI = QuoteString(string(I,URI.end() - I),"\\|{}[]<>\"^~_=!@#$%^&*");
+ string::iterator J = URI.begin();
+ for (; J != URI.end(); J++)
+ if (*J == '/')
+ *J = '_';
+ return URI;
+}
+ /*}}}*/
// Base64Encode - Base64 Encoding routine for short strings /*{{{*/
// ---------------------------------------------------------------------
/* This routine performs a base64 transformation on a string. It was ripped
// -*- mode: cpp; mode: fold -*-
// Description /*{{{*/
-// $Id: strutl.h,v 1.2 1998/07/09 05:12:35 jgg Exp $
+// $Id: strutl.h,v 1.3 1998/07/19 04:22:09 jgg Exp $
/* ######################################################################
String Util - These are some usefull string functions
string TimeToStr(unsigned long Sec);
string SubstVar(string Str,string Subst,string Contents);
string Base64Encode(string Str);
+string URItoFileName(string URI);
int stringcmp(const char *A,const char *AEnd,const char *B,const char *BEnd);
inline int stringcmp(const char *A,const char *AEnd,const char *B) {return stringcmp(A,AEnd,B,B+strlen(B));};
// -*- mode: cpp; mode: fold -*-
// Description /*{{{*/
-// $Id: pkgcache.cc,v 1.7 1998/07/12 23:58:32 jgg Exp $
+// $Id: pkgcache.cc,v 1.8 1998/07/19 04:22:00 jgg Exp $
/* ######################################################################
Package Cache - Accessor code for the cache
VersionCount = 0;
DependsCount = 0;
PackageFileCount = 0;
+ MaxVerFileSize = 0;
FileList = 0;
StringList = 0;
// -*- mode: cpp; mode: fold -*-
// Description /*{{{*/
-// $Id: pkgcache.h,v 1.6 1998/07/12 23:58:33 jgg Exp $
+// $Id: pkgcache.h,v 1.7 1998/07/19 04:22:01 jgg Exp $
/* ######################################################################
Cache - Structure definitions for the cache file
Header &Head() {return *HeaderP;};
inline PkgIterator PkgBegin();
inline PkgIterator PkgEnd();
-
+ inline PkgFileIterator FileBegin();
+ inline PkgFileIterator FileEnd();
+
pkgCache(MMap &Map);
virtual ~pkgCache() {};
};
// Offsets
unsigned long FileList; // struct PackageFile
unsigned long StringList; // struct StringItem
+ unsigned long MaxVerFileSize;
/* Allocation pools, there should be one of these for each structure
excluding the header */
{return PkgIterator(*this);};
inline pkgCache::PkgIterator pkgCache::PkgEnd()
{return PkgIterator(*this,PkgP);};
+inline pkgCache::PkgFileIterator pkgCache::FileBegin()
+ {return PkgFileIterator(*this);};
+inline pkgCache::PkgFileIterator pkgCache::FileEnd()
+ {return PkgFileIterator(*this,PkgFileP);};
#endif
// -*- mode: cpp; mode: fold -*-
// Description /*{{{*/
-// $Id: pkgcachegen.cc,v 1.10 1998/07/16 06:08:38 jgg Exp $
+// $Id: pkgcachegen.cc,v 1.11 1998/07/19 04:22:02 jgg Exp $
/* ######################################################################
Package Cache Generator - Generator for the cache structure.
Ver->FileList = VF.Index();
VF->Offset = List.Offset();
VF->Size = List.Size();
-
+ if (Cache.HeaderP->MaxVerFileSize < VF->Size)
+ Cache.HeaderP->MaxVerFileSize = VF->Size;
return true;
}
/*}}}*/
CurrentFile->NextFile = Cache.HeaderP->FileList;
CurrentFile->Flags = Flags;
PkgFileName = File;
-
+ Cache.HeaderP->FileList = CurrentFile - Cache.PkgFileP;
+
if (CurrentFile->FileName == 0)
return false;
return true;
// -*- mode: cpp; mode: fold -*-
// Description /*{{{*/
-// $Id: pkgcachegen.h,v 1.5 1998/07/12 23:58:35 jgg Exp $
+// $Id: pkgcachegen.h,v 1.6 1998/07/19 04:22:03 jgg Exp $
/* ######################################################################
Package Cache Generator - Generator for the cache structure.
pkgCache::VerIterator Ver) = 0;
virtual unsigned long Offset() = 0;
virtual unsigned long Size() = 0;
-
+
virtual bool Step() = 0;
virtual ~ListParser() {};
bool SelectFile(string File,unsigned long Flags = 0);
bool MergeList(ListParser &List);
-
+ inline pkgCache &GetCache() {return Cache;};
+
pkgCacheGenerator(DynamicMMap &Map);
~pkgCacheGenerator();
};
// -*- mode: cpp; mode: fold -*-
// Description /*{{{*/
-// $Id: sourcelist.cc,v 1.3 1998/07/12 23:58:36 jgg Exp $
+// $Id: sourcelist.cc,v 1.4 1998/07/19 04:22:04 jgg Exp $
/* ######################################################################
List of Sources
return true;
}
/*}}}*/
-// SourceList::SanitizeURI - Hash the uri /*{{{*/
-// ---------------------------------------------------------------------
-/* This converts a URI into a safe filename. It quotes all unsafe characters
- and converts / to _ and removes the scheme identifier. */
-string pkgSourceList::SanitizeURI(string URI)
-{
- string::const_iterator I = URI.begin() + URI.find(':') + 1;
- for (; I < URI.end() && *I == '/'; I++);
-
- // "\x00-\x20{}|\\\\^\\[\\]<>\"\x7F-\xFF";
- URI = QuoteString(string(I,URI.end() - I),"\\|{}[]<>\"^~_=!@#$%^&*");
- string::iterator J = URI.begin();
- for (; J != URI.end(); J++)
- if (*J == '/')
- *J = '_';
- return URI;
-}
- /*}}}*/
-// SourceList::MatchPkgFile - Find the package file that has the ver /*{{{*/
-// ---------------------------------------------------------------------
-/* This will return List.end() if it could not find the matching
- file */
-pkgSourceList::const_iterator pkgSourceList::MatchPkgFile(pkgCache::VerIterator Ver)
-{
- string Base = _config->Find("APT::Architecture");
- for (const_iterator I = List.begin(); I != List.end(); I++)
- {
- string URI = I->PackagesURI();
- switch (I->Type)
- {
- case Item::Deb:
-/* if (Base + SanitizeURI(URI) == Ver.File().FileName())
- return I;*/
- break;
- };
- }
- return List.end();
-}
- /*}}}*/
// SourceList::Item << - Writes the item to a stream /*{{{*/
// ---------------------------------------------------------------------
/* This is not suitable for rebuilding the sourcelist file but it good for
// -*- mode: cpp; mode: fold -*-
// Description /*{{{*/
-// $Id: sourcelist.h,v 1.3 1998/07/12 23:58:38 jgg Exp $
+// $Id: sourcelist.h,v 1.4 1998/07/19 04:22:05 jgg Exp $
/* ######################################################################
SourceList - Manage a list of sources
bool ReadMainList();
bool Read(string File);
- string SanitizeURI(string URI);
- const_iterator MatchPkgFile(pkgCache::VerIterator Ver);
// List accessors
inline const_iterator begin() const {return List.begin();};
// -*- mode: cpp; mode: fold -*-
// Description /*{{{*/
-// $Id: tagfile.cc,v 1.8 1998/07/16 06:08:39 jgg Exp $
+// $Id: tagfile.cc,v 1.9 1998/07/19 04:22:06 jgg Exp $
/* ######################################################################
Fast scanner for RFC-822 type header information
- This uses a rotating 64K buffer to load the package information into.
+ This uses a rotating buffer to load the package information into.
The scanner runs over it and isolates and indexes a single section.
##################################################################### */
// TagFile::pkgTagFile - Constructor /*{{{*/
// ---------------------------------------------------------------------
/* */
-pkgTagFile::pkgTagFile(File &Fd) : Fd(Fd)
+pkgTagFile::pkgTagFile(File &Fd,unsigned long Size) : Fd(Fd), Size(Size)
{
- Buffer = new char[64*1024];
- Start = End = Buffer + 64*1024;
+ Buffer = new char[Size];
+ Start = End = Buffer;
Left = Fd.Size();
iOffset = 0;
Fill();
then fills the rest from the file */
bool pkgTagFile::Fill()
{
- unsigned long Size = End - Start;
+ unsigned long EndSize = End - Start;
if (Left == 0)
{
- if (Size <= 1)
+ if (EndSize <= 1)
return false;
return true;
}
- memmove(Buffer,Start,Size);
+ memmove(Buffer,Start,EndSize);
Start = Buffer;
+ End = Buffer + EndSize;
- // See if only a bit of the file is left or if
- if (Left < End - Buffer - Size)
+ // See if only a bit of the file is left
+ if (Left < Size)
{
- if (Fd.Read(Buffer + Size,Left) == false)
+ if (Fd.Read(End,Left) == false)
return false;
- End = Buffer + Size + Left;
+ End += Left;
Left = 0;
}
else
{
- if (Fd.Read(Buffer + Size, End - Buffer - Size) == false)
+ if (Fd.Read(End,Size - (End - Buffer)) == false)
return false;
- Left -= End - Buffer - Size;
+ Left -= Size - (End - Buffer);
+ End = Buffer + Size;
}
return true;
}
/*}}}*/
+// TagFile::Jump - Jump to a pre-recorded location in the file /*{{{*/
+// ---------------------------------------------------------------------
+/* This jumps to a pre-recorded file location and */
+bool pkgTagFile::Jump(pkgTagSection &Tag,unsigned long Offset)
+{
+ iOffset = Offset;
+ Left = Fd.Size() - Offset;
+ if (Fd.Seek(Offset) == false)
+ return false;
+ End = Start = Buffer;
+
+ if (Fill() == false)
+ return false;
+
+ if (Tag.Scan(Start,End - Start) == false)
+ return _error->Error("Unable to parse package file");
+ return true;
+}
+ /*}}}*/
// TagSection::Scan - Scan for the end of the header information /*{{{*/
// ---------------------------------------------------------------------
/* This looks for the first double new line in the data stream. It also
// -*- mode: cpp; mode: fold -*-
// Description /*{{{*/
-// $Id: tagfile.h,v 1.5 1998/07/16 06:08:40 jgg Exp $
+// $Id: tagfile.h,v 1.6 1998/07/19 04:22:07 jgg Exp $
/* ######################################################################
Fast scanner for RFC-822 type header information
char *End;
unsigned long Left;
unsigned long iOffset;
+ unsigned long Size;
bool Fill();
bool Step(pkgTagSection &Section);
inline unsigned long Offset() {return iOffset;};
-
- pkgTagFile(File &F);
+ bool Jump(pkgTagSection &Tag,unsigned long Offset);
+
+ pkgTagFile(File &F,unsigned long Size = 32*1024);
};
#endif
// -*- mode: cpp; mode: fold -*-
// Description /*{{{*/
-// $Id: apt-cache.cc,v 1.2 1998/07/16 06:08:43 jgg Exp $
+// $Id: apt-cache.cc,v 1.3 1998/07/19 04:22:10 jgg Exp $
/* ######################################################################
apt-cache - Manages the cache file.
return _error->Error("Malformed argument %s, must be in file:dist:rev form",Arg);
Ver = string(Start,I - Start);
- return true;
-}
- /*}}}*/
-// DoAdd - Perform an adding operation /*{{{*/
-// ---------------------------------------------------------------------
-/* */
-bool DoAdd(int argc,char *argv[])
-{
- string FileName;
- string Dist;
- string Ver;
-
- File CacheF(CacheFile,File::WriteEmpty);
- if (_error->PendingError() == true)
- return false;
-
- DynamicMMap Map(CacheF,MMap::Public);
- if (_error->PendingError() == true)
- return false;
-
- pkgCacheGenerator Gen(Map);
- if (_error->PendingError() == true)
- return false;
-
- for (int I = 0; I != argc; I++)
- {
- if (SplitArg(argv[I],FileName,Dist,Ver) == false)
- return false;
- cout << FileName << endl;
-
- // Do the merge
- File TagF(FileName.c_str(),File::ReadOnly);
- debListParser Parser(TagF);
- if (_error->PendingError() == true)
- return _error->Error("Problem opening %s",FileName.c_str());
-
- if (Gen.SelectFile(FileName) == false)
- return _error->Error("Problem with SelectFile");
-
- if (Gen.MergeList(Parser) == false)
- return _error->Error("Problem with MergeList");
- }
-
return true;
}
/*}}}*/
// DumpPackage - Show a dump of a package record /*{{{*/
// ---------------------------------------------------------------------
/* */
-bool DumpPackage(int argc,char *argv[])
-{
- File CacheF(CacheFile,File::ReadOnly);
- if (_error->PendingError() == true)
- return false;
-
- MMap Map(CacheF,MMap::Public | MMap::ReadOnly);
- if (_error->PendingError() == true)
- return false;
-
- pkgCache Cache(Map);
- if (_error->PendingError() == true)
- return false;
-
+bool DumpPackage(pkgCache &Cache,int argc,char *argv[])
+{
for (int I = 0; I != argc; I++)
{
pkgCache::PkgIterator Pkg = Cache.FindPkg(argv[I]);
// Stats - Dump some nice statistics /*{{{*/
// ---------------------------------------------------------------------
/* */
-bool Stats(const char *FileName)
+bool Stats(pkgCache &Cache)
{
- File CacheF(FileName,File::ReadOnly);
- if (_error->PendingError() == true)
- return false;
-
- MMap Map(CacheF,MMap::Public | MMap::ReadOnly);
- if (_error->PendingError() == true)
- return false;
-
- pkgCache Cache(Map);
- if (_error->PendingError() == true)
- return false;
-
cout << "Total Package Names : " << Cache.Head().PackageCount << endl;
pkgCache::PkgIterator I = Cache.PkgBegin();
// Dump - show everything /*{{{*/
// ---------------------------------------------------------------------
/* */
-bool Dump()
+bool Dump(pkgCache &Cache)
{
- File CacheF(CacheFile,File::ReadOnly);
- if (_error->PendingError() == true)
- return false;
-
- MMap Map(CacheF,MMap::Public | MMap::ReadOnly);
- if (_error->PendingError() == true)
- return false;
-
- pkgCache Cache(Map);
- if (_error->PendingError() == true)
- return false;
-
for (pkgCache::PkgIterator P = Cache.PkgBegin(); P.end() == false; P++)
{
cout << "Package: " << P.Name() << endl;
// DumpAvail - Print out the available list /*{{{*/
// ---------------------------------------------------------------------
/* This is needed to make dpkg --merge happy */
-bool DumpAvail()
+bool DumpAvail(pkgCache &Cache)
{
-#if 0
- pkgCache Cache(CacheFile,true,true);
- if (_error->PendingError() == true)
- return false;
+ unsigned char *Buffer = new unsigned char[Cache.HeaderP->MaxVerFileSize];
- pkgControlCache CCache(Cache);
- if (_error->PendingError() == true)
- return false;
-
- vector<string> Lines;
- Lines.reserve(30);
-
- pkgCache::PkgIterator I = Cache.PkgBegin();
- for (;I.end() != true; I++)
+ for (pkgCache::PkgFileIterator I = Cache.FileBegin(); I.end() == false; I++)
{
- if (I->VersionList == 0)
+ if ((I->Flags & pkgCache::Flag::NotSource) != 0)
continue;
- pkgSPkgCtrlInfo Inf = CCache[I.VersionList()];
- if (Inf.isNull() == true)
- return _error->Error("Couldn't locate info record");
+ if (I.IsOk() == false)
+ {
+ delete [] Buffer;
+ return _error->Error("Package file %s is out of sync.",I.FileName());
+ }
- // Iterate over each element
- pkgPkgCtrlInfo::const_iterator Elm = Inf->begin();
- for (; Elm != Inf->end(); Elm++)
+ File PkgF(I.FileName(),File::ReadOnly);
+ if (_error->PendingError() == true)
{
- // Write the tag: value
- cout << (*Elm)->Tag() << ": " << (*Elm)->Value() << endl;
-
- // Write the multiline
- (*Elm)->GetLines(Lines);
- for (vector<string>::iterator j = Lines.begin(); j != Lines.end(); j++)
+ delete [] Buffer;
+ return false;
+ }
+
+ /* Write all of the records from this package file, we search the entire
+ structure to find them */
+ for (pkgCache::PkgIterator P = Cache.PkgBegin(); P.end() == false; P++)
+ {
+ for (pkgCache::VerIterator V = P.VersionList(); V.end() == false; V++)
{
- if ((*j).length() == 0)
- cout << " ." << endl;
- else
- cout << " " << *j << endl;
+ if (V->FileList == 0)
+ continue;
+ if (V.FileList().File() != I)
+ continue;
+
+ // Read the record and then write it out again.
+ if (PkgF.Seek(V.FileList()->Offset) == false ||
+ PkgF.Read(Buffer,V.FileList()->Size) == false ||
+ write(STDOUT_FILENO,Buffer,V.FileList()->Size) != V.FileList()->Size)
+ {
+ delete [] Buffer;
+ return false;
+ }
}
-
- Lines.erase(Lines.begin(),Lines.end());
}
+ }
+
+ return true;
+}
+ /*}}}*/
+// DoAdd - Perform an adding operation /*{{{*/
+// ---------------------------------------------------------------------
+/* */
+bool DoAdd(int argc,char *argv[])
+{
+ string FileName;
+ string Dist;
+ string Ver;
+
+ // Open the cache
+ File CacheF(CacheFile,File::WriteEmpty);
+ if (_error->PendingError() == true)
+ return false;
+
+ DynamicMMap Map(CacheF,MMap::Public);
+ if (_error->PendingError() == true)
+ return false;
+
+ pkgCacheGenerator Gen(Map);
+ if (_error->PendingError() == true)
+ return false;
+
+ for (int I = 0; I != argc; I++)
+ {
+ if (SplitArg(argv[I],FileName,Dist,Ver) == false)
+ return false;
+ cout << FileName << endl;
- cout << endl;
+ // Do the merge
+ File TagF(FileName.c_str(),File::ReadOnly);
+ debListParser Parser(TagF);
+ if (_error->PendingError() == true)
+ return _error->Error("Problem opening %s",FileName.c_str());
+
+ if (Gen.SelectFile(FileName) == false)
+ return _error->Error("Problem with SelectFile");
+
+ if (Gen.MergeList(Parser) == false)
+ return _error->Error("Problem with MergeList");
}
-#endif
+
+ Stats(Gen.GetCache());
+
return true;
}
/*}}}*/
pkgInitialize(*_config);
while (1)
{
+ CacheFile = argv[2];
if (strcmp(argv[1],"add") == 0)
{
- CacheFile = argv[2];
- if (DoAdd(argc - 3,argv + 3) == true)
- Stats(argv[2]);
+ DoAdd(argc - 3,argv + 3);
break;
}
+
+ // Open the cache file
+ File CacheF(CacheFile,File::ReadOnly);
+ if (_error->PendingError() == true)
+ break;
+
+ MMap Map(CacheF,MMap::Public | MMap::ReadOnly);
+ if (_error->PendingError() == true)
+ break;
+
+ pkgCache Cache(Map);
+ if (_error->PendingError() == true)
+ break;
if (strcmp(argv[1],"showpkg") == 0)
{
CacheFile = argv[2];
- DumpPackage(argc - 3,argv + 3);
+ DumpPackage(Cache,argc - 3,argv + 3);
break;
}
if (strcmp(argv[1],"stats") == 0)
{
- Stats(argv[2]);
+ Stats(Cache);
break;
}
if (strcmp(argv[1],"dump") == 0)
{
- CacheFile = argv[2];
- Dump();
+ Dump(Cache);
break;
}
if (strcmp(argv[1],"dumpavail") == 0)
{
- CacheFile = argv[2];
- DumpAvail();
+ DumpAvail(Cache);
break;
}
<title>APT Cache File Format</title>
<author>Jason Gunthorpe <email>jgg@debian.org</email></author>
-<version>$Id: cache.sgml,v 1.2 1998/07/05 05:43:09 jgg Exp $</version>
+<version>$Id: cache.sgml,v 1.3 1998/07/19 04:22:11 jgg Exp $</version>
<abstract>
This document describes the complete implementation and format of the APT
unsigned long VersionCount;
unsigned long DependsCount;
unsigned long PackageFileCount;
+ unsigned long MaxVerFileSize;
// Offsets
unsigned long FileList; // PackageFile
PackageCount is especially usefull for generating user state structures.
See Package::Id for more info.
+<tag>MaxVerFileSize<item>
+The maximum size of a raw entry from the original Package file
+(ie VerFile::Size) is stored here.
+
<tag>FileList<item>
This contains the index of the first PackageFile structure. The PackageFile
structures are singely linked lists that represent all package files that