X-Git-Url: https://git.saurik.com/apt.git/blobdiff_plain/1164783d22d97e7ca0454e23faad8f8bb70a901d..f760b7d2124f9b4498b62c481f08e56cc617e675:/cmdline/apt-cache.cc diff --git a/cmdline/apt-cache.cc b/cmdline/apt-cache.cc index ce7ccc2c9..3f50f0c02 100644 --- a/cmdline/apt-cache.cc +++ b/cmdline/apt-cache.cc @@ -1,23 +1,14 @@ // -*- mode: cpp; mode: fold -*- // Description /*{{{*/ -// $Id: apt-cache.cc,v 1.1 1998/07/15 05:56:47 jgg Exp $ +// $Id: apt-cache.cc,v 1.33 1999/04/12 04:21:20 jgg Exp $ /* ###################################################################### - apt-cache - Manages the cache file. + apt-cache - Manages the cache files - This program should eventually handle both low and high level - manipulation of the cache file. Depending how far things go it - might get quite a sophisticated UI. - - Currently the command line is as follows: - apt-cache add cache file1:dist:ver file2:dist:ver ... - ie: - apt-cache add ./cache Pacakges:hamm:1.0 - - A usefull feature is 'upgradable' ie - apt-cache upgradable ./cache - will list .debs that should be installed to make all packages the latest - version. + apt-cache provides some functions fo manipulating the cache files. + It uses the command line interface common to all the APT tools. The + only really usefull function right now is dumpavail which is used + by the dselect method. Everything else is ment as a debug aide. Returns 100 on failure, 0 on success. @@ -27,114 +18,139 @@ #include #include #include +#include +#include +#include +#include +#include +#include +#include #include -#include - +#include +#include +#include /*}}}*/ -string CacheFile; +pkgCache *GCache = 0; -// SplitArg - Split the triple /*{{{*/ +// UnMet - Show unmet dependencies /*{{{*/ // --------------------------------------------------------------------- /* */ -bool SplitArg(const char *Arg,string &File,string &Dist,string Ver) +bool UnMet(CommandLine &CmdL) { - const char *Start = Arg; - const char *I = Arg; - for (;*I != 0 && *I != ':'; I++); - if (*I != ':') - return _error->Error("Malformed argument %s, must be in file:dist:rev form",Arg); - File = string(Start,I - Start); - - I++; - Start = I; - for (;*I != 0 && *I != ':'; I++); - if (*I != ':') - return _error->Error("Malformed argument %s, must be in file:dist:rev form",Arg); - Dist = string(Start,I - Start); + pkgCache &Cache = *GCache; + bool Important = _config->FindB("APT::Cache::Important",false); - I++; - Start = I; - for (;*I != 0 && *I != ':'; I++); - if (I == Start) - return _error->Error("Malformed argument %s, must be in file:dist:rev form",Arg); - Ver = string(Start,I - Start); + for (pkgCache::PkgIterator P = Cache.PkgBegin(); P.end() == false; P++) + { + for (pkgCache::VerIterator V = P.VersionList(); V.end() == false; V++) + { + bool Header = false; + for (pkgCache::DepIterator D = V.DependsList(); D.end() == false;) + { + // Collect or groups + pkgCache::DepIterator Start; + pkgCache::DepIterator End; + D.GlobOr(Start,End); + +/* cout << "s: Check " << Start.TargetPkg().Name() << ',' << + End.TargetPkg().Name() << endl;*/ + + // Skip conflicts and replaces + if (End->Type != pkgCache::Dep::PreDepends && + End->Type != pkgCache::Dep::Depends && + End->Type != pkgCache::Dep::Suggests && + End->Type != pkgCache::Dep::Recommends) + continue; - 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; + // Important deps only + if (Important == true) + if (End->Type != pkgCache::Dep::PreDepends && + End->Type != pkgCache::Dep::Depends) + continue; + + // Verify the or group + bool OK = false; + pkgCache::DepIterator RealStart = Start; + do + { + // See if this dep is Ok + pkgCache::Version **VList = Start.AllTargets(); + if (*VList != 0) + { + OK = true; + delete [] VList; + break; + } + delete [] VList; + + if (Start == End) + break; + Start++; + } + while (1); - for (int I = 0; I != argc; I++) - { - if (SplitArg(argv[I],FileName,Dist,Ver) == false) - return false; - - // Do the merge - File TagF(FileName.c_str(),File::ReadOnly); - debListParser Parser(TagF); - if (_error->PendingError() == true) - return false; - if (Gen.SelectFile(FileName) == false) - return false; - - if (Gen.MergeList(Parser) == false) - return false; - } - + // The group is OK + if (OK == true) + continue; + + // Oops, it failed.. + if (Header == false) + cout << "Package " << P.Name() << " version " << + V.VerStr() << " has an unmet dep:" << endl; + Header = true; + + // Print out the dep type + cout << " " << End.DepType() << ": "; + + // Show the group + Start = RealStart; + do + { + cout << Start.TargetPkg().Name(); + if (Start.TargetVer() != 0) + cout << " (" << Start.CompType() << " " << Start.TargetVer() << + ")"; + if (Start == End) + break; + cout << " | "; + Start++; + } + while (1); + + cout << endl; + } + } + } 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; - - for (int I = 0; I != argc; I++) +bool DumpPackage(CommandLine &CmdL) +{ + pkgCache &Cache = *GCache; + for (const char **I = CmdL.FileList + 1; *I != 0; I++) { - pkgCache::PkgIterator Pkg = Cache.FindPkg(argv[I]); + pkgCache::PkgIterator Pkg = Cache.FindPkg(*I); if (Pkg.end() == true) { - _error->Warning("Unable to locate package %s",argv[0]); + _error->Warning("Unable to locate package %s",*I); continue; } cout << "Package: " << Pkg.Name() << endl; cout << "Versions: "; for (pkgCache::VerIterator Cur = Pkg.VersionList(); Cur.end() != true; Cur++) - cout << Cur.VerStr() << ','; + { + cout << Cur.VerStr(); + for (pkgCache::VerFileIterator Vf = Cur.FileList(); Vf.end() == false; Vf++) + cout << "(" << Vf.File().FileName() << ")"; + cout << ','; + } + cout << endl; cout << "Reverse Depends: " << endl; @@ -157,7 +173,12 @@ bool DumpPackage(int argc,char *argv[]) for (pkgCache::PrvIterator Prv = Cur.ProvidesList(); Prv.end() != true; Prv++) cout << Prv.ParentPkg().Name() << " "; cout << endl; - } + } + cout << "Reverse Provides: " << endl; + for (pkgCache::PrvIterator Prv = Pkg.ProvidesList(); Prv.end() != true; Prv++) + cout << Prv.OwnerPkg().Name() << " " << Prv.OwnerVer().VerStr(); + cout << endl; + } return true; @@ -166,21 +187,11 @@ bool DumpPackage(int argc,char *argv[]) // Stats - Dump some nice statistics /*{{{*/ // --------------------------------------------------------------------- /* */ -bool Stats(const char *FileName) +bool Stats(CommandLine &Cmd) { - 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 &Cache = *GCache; + cout << "Total Package Names : " << Cache.Head().PackageCount << " (" << + SizeToStr(Cache.Head().PackageCount*Cache.Head().PackageSz) << ')' << endl; pkgCache::PkgIterator I = Cache.PkgBegin(); int Normal = 0; @@ -225,28 +236,71 @@ bool Stats(const char *FileName) cout << " Mixed Virtual Packages: " << NVirt << endl; cout << " Missing: " << Missing << endl; - cout << "Total Distinct Versions: " << Cache.Head().VersionCount << endl; - cout << "Total Dependencies: " << Cache.Head().DependsCount << endl; + cout << "Total Distinct Versions: " << Cache.Head().VersionCount << " (" << + SizeToStr(Cache.Head().VersionCount*Cache.Head().VersionSz) << ')' << endl; + cout << "Total Dependencies: " << Cache.Head().DependsCount << " (" << + SizeToStr(Cache.Head().DependsCount*Cache.Head().DependencySz) << ')' << endl; + + cout << "Total Ver/File relations: " << Cache.Head().VerFileCount << " (" << + SizeToStr(Cache.Head().VerFileCount*Cache.Head().VerFileSz) << ')' << endl; + cout << "Total Provides Mappings: " << Cache.Head().ProvidesCount << " (" << + SizeToStr(Cache.Head().ProvidesCount*Cache.Head().ProvidesSz) << ')' << endl; + + // String list stats + unsigned long Size = 0; + unsigned long Count = 0; + for (pkgCache::StringItem *I = Cache.StringItemP + Cache.Head().StringList; + I!= Cache.StringItemP; I = Cache.StringItemP + I->NextItem) + { + Count++; + Size += strlen(Cache.StrP + I->String); + } + cout << "Total Globbed Strings: " << Count << " (" << SizeToStr(Size) << ')' << endl; + + unsigned long Slack = 0; + for (int I = 0; I != 7; I++) + Slack += Cache.Head().Pools[I].ItemSize*Cache.Head().Pools[I].Count; + cout << "Total Slack space: " << SizeToStr(Slack) << endl; + + unsigned long Total = 0; + Total = Slack + Size + Cache.Head().DependsCount*Cache.Head().DependencySz + + Cache.Head().VersionCount*Cache.Head().VersionSz + + Cache.Head().PackageCount*Cache.Head().PackageSz + + Cache.Head().VerFileCount*Cache.Head().VerFileSz + + Cache.Head().ProvidesCount*Cache.Head().ProvidesSz; + cout << "Total Space Accounted for: " << SizeToStr(Total) << endl; + + return true; +} + /*}}}*/ +// Check - Check some things about the cache /*{{{*/ +// --------------------------------------------------------------------- +/* Debug aide mostly */ +bool Check(CommandLine &Cmd) +{ + pkgCache &Cache = *GCache; + pkgCache::PkgIterator Pkg = Cache.PkgBegin(); + for (;Pkg.end() != true; Pkg++) + { + if (Pkg.Section() == 0 && Pkg->VersionList != 0) + cout << "Bad section " << Pkg.Name() << endl; + + for (pkgCache::VerIterator Cur = Pkg.VersionList(); + Cur.end() != true; Cur++) + { + if (Cur->Priority < 1 || Cur->Priority > 5) + cout << "Bad prio " << Pkg.Name() << ',' << Cur.VerStr() << " == " << (int)Cur->Priority << endl; + } + } return true; } /*}}}*/ // Dump - show everything /*{{{*/ // --------------------------------------------------------------------- /* */ -bool Dump() +bool Dump(CommandLine &Cmd) { - 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; - + pkgCache &Cache = *GCache; for (pkgCache::PkgIterator P = Cache.PkgBegin(); P.end() == false; P++) { cout << "Package: " << P.Name() << endl; @@ -265,7 +319,13 @@ bool Dump() cout << " Size: " << F->Size << endl; cout << " ID: " << F->ID << endl; cout << " Flags: " << F->Flags << endl; - cout << " Time: " << ctime(&F->mtime) << endl; + cout << " Time: " << TimeRFC1123(F->mtime) << endl; + cout << " Archive: " << F.Archive() << endl; + cout << " Component: " << F.Component() << endl; + cout << " Version: " << F.Version() << endl; + cout << " Origin: " << F.Origin() << endl; + cout << " Label: " << F.Label() << endl; + cout << " Architecture: " << F.Architecture() << endl; } return true; @@ -274,112 +334,347 @@ bool Dump() // DumpAvail - Print out the available list /*{{{*/ // --------------------------------------------------------------------- /* This is needed to make dpkg --merge happy */ -bool DumpAvail() +bool DumpAvail(CommandLine &Cmd) { -#if 0 - pkgCache Cache(CacheFile,true,true); + pkgCache &Cache = *GCache; + unsigned char *Buffer = new unsigned char[Cache.HeaderP->MaxVerFileSize]; + + for (pkgCache::PkgFileIterator I = Cache.FileBegin(); I.end() == false; I++) + { + if ((I->Flags & pkgCache::Flag::NotSource) != 0) + continue; + + if (I.IsOk() == false) + { + delete [] Buffer; + return _error->Error("Package file %s is out of sync.",I.FileName()); + } + + FileFd PkgF(I.FileName(),FileFd::ReadOnly); + if (_error->PendingError() == true) + { + 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++) + { + // Find the proper version to use. We should probably use the DepCache. + pkgCache::VerIterator V = Cache.GetCandidateVer(P,false); + + if (V.end() == true || 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; + } + } + } + + return true; +} + /*}}}*/ +// DoAdd - Perform an adding operation /*{{{*/ +// --------------------------------------------------------------------- +/* */ +bool DoAdd(CommandLine &CmdL) +{ + // Make sure there is at least one argument + if (CmdL.FileSize() <= 1) + return _error->Error("You must give at least one file name"); + + // Open the cache + FileFd CacheF(_config->FindFile("Dir::Cache::pkgcache"),FileFd::WriteAny); + if (_error->PendingError() == true) + return false; + + DynamicMMap Map(CacheF,MMap::Public); if (_error->PendingError() == true) return false; - pkgControlCache CCache(Cache); + OpTextProgress Progress(*_config); + pkgCacheGenerator Gen(Map,Progress); + if (_error->PendingError() == true) + return false; + + unsigned long Length = CmdL.FileSize() - 1; + for (const char **I = CmdL.FileList + 1; *I != 0; I++) + { + Progress.OverallProgress(I - CmdL.FileList,Length,1,"Generating cache"); + Progress.SubProgress(Length); + + // Do the merge + FileFd TagF(*I,FileFd::ReadOnly); + debListParser Parser(TagF); + if (_error->PendingError() == true) + return _error->Error("Problem opening %s",*I); + + if (Gen.SelectFile(*I) == false) + return _error->Error("Problem with SelectFile"); + + if (Gen.MergeList(Parser) == false) + return _error->Error("Problem with MergeList"); + } + + Progress.Done(); + GCache = &Gen.GetCache(); + Stats(CmdL); + + return true; +} + /*}}}*/ +// DisplayRecord - Displays the complete record for the package /*{{{*/ +// --------------------------------------------------------------------- +/* This displays the package record from the proper package index file. + It is not used by DumpAvail for performance reasons. */ +bool DisplayRecord(pkgCache::VerIterator V) +{ + // Find an appropriate file + pkgCache::VerFileIterator Vf = V.FileList(); + for (; Vf.end() == false; Vf++) + if ((Vf.File()->Flags & pkgCache::Flag::NotSource) == 0) + break; + if (Vf.end() == true) + Vf = V.FileList(); + + // Check and load the package list file + pkgCache::PkgFileIterator I = Vf.File(); + if (I.IsOk() == false) + return _error->Error("Package file %s is out of sync.",I.FileName()); + + FileFd PkgF(I.FileName(),FileFd::ReadOnly); if (_error->PendingError() == true) return false; + + // Read the record and then write it out again. + unsigned char *Buffer = new unsigned char[GCache->HeaderP->MaxVerFileSize]; + 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; + } + + delete [] Buffer; - vector Lines; - Lines.reserve(30); + return true; +} + /*}}}*/ +// Search - Perform a search /*{{{*/ +// --------------------------------------------------------------------- +/* This searches the package names and pacakge descriptions for a pattern */ +bool Search(CommandLine &CmdL) +{ + pkgCache &Cache = *GCache; + bool ShowFull = _config->FindB("APT::Cache::ShowFull",false); + bool NamesOnly = _config->FindB("APT::Cache::NamesOnly",false); + + // Make sure there is at least one argument + if (CmdL.FileSize() != 2) + return _error->Error("You must give exactly one pattern"); + // Compile the regex pattern + regex_t Pattern; + if (regcomp(&Pattern,CmdL.FileList[1],REG_EXTENDED | REG_ICASE | + REG_NOSUB) != 0) + return _error->Error("Regex compilation error"); + + // Create the text record parser + pkgRecords Recs(Cache); + if (_error->PendingError() == true) + return false; + + // Search package names pkgCache::PkgIterator I = Cache.PkgBegin(); for (;I.end() != true; I++) { - if (I->VersionList == 0) + // We search against the install version as that makes the most sense.. + pkgCache::VerIterator V = Cache.GetCandidateVer(I); + if (V.end() == true) continue; + + pkgRecords::Parser &P = Recs.Lookup(V.FileList()); - pkgSPkgCtrlInfo Inf = CCache[I.VersionList()]; - if (Inf.isNull() == true) - return _error->Error("Couldn't locate info record"); - - // Iterate over each element - pkgPkgCtrlInfo::const_iterator Elm = Inf->begin(); - for (; Elm != Inf->end(); Elm++) + if (regexec(&Pattern,I.Name(),0,0,0) == 0 || + (NamesOnly == false && + regexec(&Pattern,P.LongDesc().c_str(),0,0,0) == 0)) { - // Write the tag: value - cout << (*Elm)->Tag() << ": " << (*Elm)->Value() << endl; - - // Write the multiline - (*Elm)->GetLines(Lines); - for (vector::iterator j = Lines.begin(); j != Lines.end(); j++) - { - if ((*j).length() == 0) - cout << " ." << endl; - else - cout << " " << *j << endl; - } - - Lines.erase(Lines.begin(),Lines.end()); + if (ShowFull == true) + DisplayRecord(V); + else + cout << I.Name() << " - " << P.ShortDesc() << endl; + } + } + + regfree(&Pattern); + return true; +} + /*}}}*/ +// ShowPackage - Dump the package record to the screen /*{{{*/ +// --------------------------------------------------------------------- +/* */ +bool ShowPackage(CommandLine &CmdL) +{ + pkgCache &Cache = *GCache; + for (const char **I = CmdL.FileList + 1; *I != 0; I++) + { + pkgCache::PkgIterator Pkg = Cache.FindPkg(*I); + if (Pkg.end() == true) + { + _error->Warning("Unable to locate package %s",*I); + continue; } - cout << endl; + // Find the proper version to use. We should probably use the DepCache. + pkgCache::VerIterator V = Cache.GetCandidateVer(Pkg); + if (V.end() == true || V.FileList().end() == true) + continue; + if (DisplayRecord(V) == false) + return false; } -#endif return true; } /*}}}*/ +// GenCaches - Call the main cache generator /*{{{*/ +// --------------------------------------------------------------------- +/* */ +bool GenCaches(CommandLine &Cmd) +{ + OpTextProgress Progress(*_config); + + pkgSourceList List; + List.ReadMainList(); + return pkgMakeStatusCache(List,Progress); +} + /*}}}*/ +// ShowHelp - Show a help screen /*{{{*/ +// --------------------------------------------------------------------- +/* */ +bool ShowHelp(CommandLine &Cmd) +{ + cout << PACKAGE << ' ' << VERSION << " for " << ARCHITECTURE << + " compiled on " << __DATE__ << " " << __TIME__ << endl; + if (_config->FindB("version") == true) + return 100; + + cout << "Usage: apt-cache [options] command" << endl; + cout << " apt-cache [options] add file1 [file1 ...]" << endl; + cout << " apt-cache [options] showpkg pkg1 [pkg2 ...]" << endl; + cout << endl; + cout << "apt-cache is a low-level tool used to manipulate APT's binary" << endl; + cout << "cache files stored in " << _config->FindFile("Dir::Cache") << endl; + cout << "It is not ment for ordinary use only as a debug aide." << endl; + cout << endl; + cout << "Commands:" << endl; + cout << " add - Add an package file to the source cache" << endl; + cout << " gencaches - Build both the package and source cache" << endl; + cout << " showpkg - Show some general information for a single package" << endl; + cout << " stats - Show some basic statistics" << endl; + cout << " dump - Show the entire file in a terse form" << endl; + cout << " dumpavail - Print an available file to stdout" << endl; + cout << " unmet - Show unmet dependencies" << endl; + cout << " check - Check the cache a bit" << endl; + cout << " search - Search the package list for a regex pattern" << endl; + cout << " show - Show a readable record for the package" << endl; + cout << endl; + cout << "Options:" << endl; + cout << " -h This help text." << endl; + cout << " -p=? The package cache. [" << _config->FindFile("Dir::Cache::pkgcache") << ']' << endl; + cout << " -s=? The source cache. [" << _config->FindFile("Dir::Cache::srcpkgcache") << ']' << endl; + cout << " -q Disable progress indicator." << endl; + cout << " -i Show only important deps for the unmet command." << endl; + cout << " -c=? Read this configuration file" << endl; + cout << " -o=? Set an arbitary configuration option, eg -o dir::cache=/tmp" << endl; + cout << "See the apt-cache(8) and apt.conf(5) manual pages for more information." << endl; + return 100; +} + /*}}}*/ +// CacheInitialize - Initialize things for apt-cache /*{{{*/ +// --------------------------------------------------------------------- +/* */ +void CacheInitialize() +{ + _config->Set("quiet",0); + _config->Set("help",false); +} + /*}}}*/ -int main(int argc, char *argv[]) +int main(int argc,const char *argv[]) { - // Check arguments. - if (argc < 3) + CommandLine::Args Args[] = { + {'h',"help","help",0}, + {'v',"version","version",0}, + {'p',"pkg-cache","Dir::Cache::pkgcache",CommandLine::HasArg}, + {'s',"src-cache","Dir::Cache::srcpkgcache",CommandLine::HasArg}, + {'q',"quiet","quiet",CommandLine::IntLevel}, + {'i',"important","APT::Cache::Important",0}, + {'f',"full","APT::Cache::ShowFull",0}, + {0,"names-only","APT::Cache::NamesOnly",0}, + {'c',"config-file",0,CommandLine::ConfigFile}, + {'o',"option",0,CommandLine::ArbItem}, + {0,0,0,0}}; + CommandLine::Dispatch CmdsA[] = {{"help",&ShowHelp}, + {"add",&DoAdd}, + {"gencaches",&GenCaches}, + {0,0}}; + CommandLine::Dispatch CmdsB[] = {{"showpkg",&DumpPackage}, + {"stats",&Stats}, + {"dump",&Dump}, + {"dumpavail",&DumpAvail}, + {"unmet",&UnMet}, + {"check",&Check}, + {"search",&Search}, + {"show",&ShowPackage}, + {0,0}}; + + CacheInitialize(); + + // Parse the command line and initialize the package library + CommandLine CmdL(Args,_config); + if (pkgInitialize(*_config) == false || + CmdL.Parse(argc,argv) == false) { - cerr << "Usage is apt-cache add cache file1:dist:ver file2:dist:ver ..." << endl; + _error->DumpErrors(); return 100; } - - while (1) - { - if (strcmp(argv[1],"add") == 0) - { - CacheFile = argv[2]; - if (DoAdd(argc - 3,argv + 3) == true) - Stats(argv[2]); - break; - } - - if (strcmp(argv[1],"showpkg") == 0) - { - CacheFile = argv[2]; - DumpPackage(argc - 3,argv + 3); - break; - } - if (strcmp(argv[1],"stats") == 0) - { - Stats(argv[2]); - break; - } - - if (strcmp(argv[1],"dump") == 0) - { - CacheFile = argv[2]; - Dump(); - break; - } - - if (strcmp(argv[1],"dumpavail") == 0) + // See if the help should be shown + if (_config->FindB("help") == true || + CmdL.FileSize() == 0) + return ShowHelp(CmdL); + + // Deal with stdout not being a tty + if (ttyname(STDOUT_FILENO) == 0 && _config->FindI("quiet",0) < 1) + _config->Set("quiet","1"); + + if (CmdL.DispatchArg(CmdsA,false) == false && _error->PendingError() == false) + { + // Open the cache file + FileFd CacheF(_config->FindFile("Dir::Cache::pkgcache"),FileFd::ReadOnly); + MMap Map(CacheF,MMap::Public | MMap::ReadOnly); + if (_error->PendingError() == false) { - CacheFile = argv[2]; - DumpAvail(); - break; - } - - _error->Error("Invalid operation %s", argv[1]); - break; + pkgCache Cache(Map); + GCache = &Cache; + if (_error->PendingError() == false) + CmdL.DispatchArg(CmdsB); + } } // Print any errors or warnings found during parsing if (_error->empty() == false) { + bool Errors = _error->PendingError(); _error->DumpErrors(); - return 100; + return Errors == true?100:0; } return 0;