diff options
-rw-r--r-- | cmdline/apt-cache.cc | 30 | ||||
-rw-r--r-- | cmdline/apt-cdrom.cc | 706 | ||||
-rw-r--r-- | cmdline/apt-config.cc | 29 | ||||
-rw-r--r-- | cmdline/apt-get.cc | 85 | ||||
-rw-r--r-- | cmdline/makefile | 6 |
5 files changed, 788 insertions, 68 deletions
diff --git a/cmdline/apt-cache.cc b/cmdline/apt-cache.cc index 063add348..3bdeb373c 100644 --- a/cmdline/apt-cache.cc +++ b/cmdline/apt-cache.cc @@ -1,6 +1,6 @@ // -*- mode: cpp; mode: fold -*- // Description /*{{{*/ -// $Id: apt-cache.cc,v 1.12 1998/11/14 07:20:29 jgg Exp $ +// $Id: apt-cache.cc,v 1.13 1998/11/27 01:52:53 jgg Exp $ /* ###################################################################### apt-cache - Manages the cache files @@ -219,6 +219,27 @@ bool Stats(pkgCache &Cache) return true; } /*}}}*/ +// Check - Check some things about the cache /*{{{*/ +// --------------------------------------------------------------------- +/* Debug aide mostly */ +bool Check(pkgCache &Cache) +{ + 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 /*{{{*/ // --------------------------------------------------------------------- /* */ @@ -382,6 +403,7 @@ int ShowHelp() 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 << endl; cout << "Options:" << endl; cout << " -h This help text." << endl; @@ -487,6 +509,12 @@ int main(int argc,const char *argv[]) UnMet(Cache); break; } + + if (strcmp(CmdL.FileList[0],"check") == 0) + { + Check(Cache); + break; + } _error->Error("Invalid operation %s", CmdL.FileList[0]); break; diff --git a/cmdline/apt-cdrom.cc b/cmdline/apt-cdrom.cc new file mode 100644 index 000000000..1839fdab4 --- /dev/null +++ b/cmdline/apt-cdrom.cc @@ -0,0 +1,706 @@ +// -*- mode: cpp; mode: fold -*- +// Description /*{{{*/ +// $Id: apt-cdrom.cc,v 1.1 1998/11/27 01:52:56 jgg Exp $ +/* ###################################################################### + + + ##################################################################### */ + /*}}}*/ +// Include Files /*{{{*/ +#include <apt-pkg/cmndline.h> +#include <apt-pkg/error.h> +#include <apt-pkg/init.h> +#include <apt-pkg/md5.h> +#include <apt-pkg/fileutl.h> +#include <apt-pkg/progress.h> +#include <apt-pkg/tagfile.h> +#include <strutl.h> +#include <config.h> + +#include <iostream> +#include <vector> +#include <algorithm> +#include <sys/wait.h> +#include <sys/errno.h> +#include <sys/vfs.h> +#include <sys/stat.h> +#include <fcntl.h> +#include <dirent.h> +#include <unistd.h> +#include <stdio.h> + /*}}}*/ + +// UnmountCdrom - Unmount a cdrom /*{{{*/ +// --------------------------------------------------------------------- +/* */ +bool UnmountCdrom(string Path) +{ + int Child = fork(); + if (Child < -1) + return _error->Errno("fork","Failed to fork"); + + // The child + if (Child == 0) + { + // Make all the fds /dev/null + for (int I = 0; I != 10;) + close(I); + for (int I = 0; I != 3;) + dup2(open("/dev/null",O_RDWR),I); + + const char *Args[10]; + Args[0] = "umount"; + Args[1] = Path.c_str(); + Args[2] = 0; + execvp(Args[0],(char **)Args); + exit(100); + } + + // Wait for mount + int Status = 0; + while (waitpid(Child,&Status,0) != Child) + { + if (errno == EINTR) + continue; + return _error->Errno("waitpid","Couldn't wait for subprocess"); + } + + // Check for an error code. + if (WIFEXITED(Status) == 0 || WEXITSTATUS(Status) != 0) + return false; + return true; +} + /*}}}*/ +// MountCdrom - Mount a cdrom /*{{{*/ +// --------------------------------------------------------------------- +/* We fork mount.. */ +bool MountCdrom(string Path) +{ + int Child = fork(); + if (Child < -1) + return _error->Errno("fork","Failed to fork"); + + // The child + if (Child == 0) + { + // Make all the fds /dev/null + for (int I = 0; I != 10;) + close(I); + for (int I = 0; I != 3;) + dup2(open("/dev/null",O_RDWR),I); + + const char *Args[10]; + Args[0] = "mount"; + Args[1] = Path.c_str(); + Args[2] = 0; + execvp(Args[0],(char **)Args); + exit(100); + } + + // Wait for mount + int Status = 0; + while (waitpid(Child,&Status,0) != Child) + { + if (errno == EINTR) + continue; + return _error->Errno("waitpid","Couldn't wait for subprocess"); + } + + // Check for an error code. + if (WIFEXITED(Status) == 0 || WEXITSTATUS(Status) != 0) + return false; + return true; +} + /*}}}*/ +// IdentCdrom - Generate a unique string for this CD /*{{{*/ +// --------------------------------------------------------------------- +/* We convert everything we hash into a string, this prevents byte size/order + from effecting the outcome. */ +bool IdentCdrom(string CD,string &Res) +{ + MD5Summation Hash; + + string StartDir = SafeGetCWD(); + if (chdir(CD.c_str()) != 0) + return _error->Errno("chdir","Unable to change to %s",CD.c_str()); + + DIR *D = opendir("."); + if (D == 0) + return _error->Errno("opendir","Unable to read %s",CD.c_str()); + + // Run over the directory + char S[300]; + for (struct dirent *Dir = readdir(D); Dir != 0; Dir = readdir(D)) + { + // Skip some files.. + if (strcmp(Dir->d_name,".") == 0 || + strcmp(Dir->d_name,"..") == 0) + continue; + + sprintf(S,"%lu",Dir->d_ino); + Hash.Add(S); + Hash.Add(Dir->d_name); + }; + + chdir(StartDir.c_str()); + closedir(D); + + // Some stats from the fsys + struct statfs Buf; + if (statfs(CD.c_str(),&Buf) != 0) + return _error->Errno("statfs","Failed to stat the cdrom"); + + sprintf(S,"%u %u",Buf.f_blocks,Buf.f_bfree); + Hash.Add(S); + + Res = Hash.Result().Value(); + return true; +} + /*}}}*/ + +// FindPackage - Find the package files on the CDROM /*{{{*/ +// --------------------------------------------------------------------- +/* We look over the cdrom for package files. This is a recursive + search that short circuits when it his a package file in the dir. + This speeds it up greatly as the majority of the size is in the + binary-* sub dirs. */ +bool FindPackages(string CD,vector<string> &List, int Depth = 0) +{ + if (Depth >= 5) + return true; + + if (CD[CD.length()-1] != '/') + CD += '/'; + + if (chdir(CD.c_str()) != 0) + return _error->Errno("chdir","Unable to change to %s",CD.c_str()); + + /* Aha! We found some package files. We assume that everything under + this dir is controlled by those package files so we don't look down + anymore */ + struct stat Buf; + if (stat("Packages",&Buf) == 0 || + stat("Packages.gz",&Buf) == 0) + { + List.push_back(CD); + return true; + } + + DIR *D = opendir("."); + if (D == 0) + return _error->Errno("opendir","Unable to read %s",CD.c_str()); + + // Run over the directory + for (struct dirent *Dir = readdir(D); Dir != 0; Dir = readdir(D)) + { + // Skip some files.. + if (strcmp(Dir->d_name,".") == 0 || + strcmp(Dir->d_name,"..") == 0 || + strcmp(Dir->d_name,"source") == 0 || + strcmp(Dir->d_name,"experimental") == 0 || + strcmp(Dir->d_name,"binary-all") == 0) + continue; + + // See if the name is a sub directory + struct stat Buf; + if (stat(Dir->d_name,&Buf) != 0) + { + _error->Errno("Stat","Stat failed for %s",Dir->d_name); + break; + } + + if (S_ISDIR(Buf.st_mode) == 0) + continue; + + // Descend + if (FindPackages(CD + Dir->d_name,List,Depth+1) == false) + break; + + if (chdir(CD.c_str()) != 0) + return _error->Errno("chdir","Unable to change to ",CD.c_str()); + }; + + closedir(D); + + return !_error->PendingError(); +} + /*}}}*/ +// CopyPackages - Copy the package files from the CD /*{{{*/ +// --------------------------------------------------------------------- +/* */ +bool CopyPackages(string CDROM,string Name,vector<string> &List) +{ + OpTextProgress Progress; + + bool NoStat = _config->FindB("APT::CDROM::Fast",false); + + // Prepare the progress indicator + unsigned long TotalSize = 0; + for (vector<string>::iterator I = List.begin(); I != List.end(); I++) + { + struct stat Buf; + if (stat(string(*I + "Packages").c_str(),&Buf) != 0) + return _error->Errno("stat","Stat failed for %s", + string(*I + "Packages").c_str()); + TotalSize += Buf.st_size; + } + + unsigned long CurrentSize = 0; + unsigned int NotFound = 0; + unsigned int WrongSize = 0; + unsigned int Packages = 0; + for (vector<string>::iterator I = List.begin(); I != List.end(); I++) + { + // Open the package file + FileFd Pkg(*I + "Packages",FileFd::ReadOnly); + pkgTagFile Parser(Pkg); + if (_error->PendingError() == true) + return false; + + // Open the output file + char S[400]; + sprintf(S,"cdrom:%s/%sPackages",Name.c_str(),(*I).c_str() + CDROM.length()); + string TargetF = _config->FindDir("Dir::State::lists") + "partial/"; + FileFd Target(TargetF + URItoFileName(S),FileFd::WriteEmpty); + if (_error->PendingError() == true) + return false; + + // Setup the progress meter + Progress.OverallProgress(CurrentSize,TotalSize,Pkg.Size(), + "Reading Package Lists"); + + // Parse + Progress.SubProgress(Pkg.Size()); + pkgTagSection Section; + while (Parser.Step(Section) == true) + { + Progress.Progress(Parser.Offset()); + + string File = Section.FindS("Filename"); + unsigned long Size = Section.FindI("Size"); + if (File.empty() || Size == 0) + return _error->Error("Cannot find filename or size tag"); + + // See if the file exists + if (NoStat == false) + { + struct stat Buf; + File = CDROM + File; + if (stat(File.c_str(),&Buf) != 0) + { + NotFound++; + continue; + } + + // Size match + if ((unsigned)Buf.st_size != Size) + { + WrongSize++; + continue; + } + } + + Packages++; + + // Copy it to the target package file + const char *Start; + const char *Stop; + Section.GetSection(Start,Stop); + if (Target.Write(Start,Stop-Start) == false) + return false; + } + + CurrentSize += Pkg.Size(); + } + Progress.Done(); + + // Some stats + cout << "Wrote " << Packages << " package records" ; + if (NotFound != 0) + cout << " with " << NotFound << " missing files"; + if (NotFound != 0 && WrongSize != 0) + cout << " and"; + if (WrongSize != 0) + cout << " with " << WrongSize << " mismatched files"; + cout << '.' << endl; + if (NotFound + WrongSize > 10) + cout << "Alot of package entires were discarded, perhaps this CD is funny?" << endl; +} + /*}}}*/ +// DropBinaryArch - Dump dirs with a string like /binary-<foo>/ /*{{{*/ +// --------------------------------------------------------------------- +/* Here we drop everything that is not this machines arch */ +bool DropBinaryArch(vector<string> &List) +{ + char S[300]; + sprintf(S,"/binary-%s/",_config->Find("Apt::Architecture").c_str()); + + for (unsigned int I = 0; I < List.size(); I++) + { + const char *Str = List[I].c_str(); + + const char *Res; + if ((Res = strstr(Str,"/binary-")) == 0) + continue; + + // Weird, remove it. + if (strlen(Res) < strlen(S)) + { + List.erase(List.begin() + I); + I--; + continue; + } + + // See if it is our arch + if (stringcmp(Res,Res + strlen(S),S) == 0) + continue; + + // Erase it + List.erase(List.begin() + I); + I--; + } + + return true; +} + /*}}}*/ +// Score - We compute a 'score' for a path /*{{{*/ +// --------------------------------------------------------------------- +/* Paths are scored based on how close they come to what I consider + normal. That is ones that have 'dist' 'stable' 'frozen' will score + higher than ones without. */ +int Score(string Path) +{ + int Res = 0; + if (Path.find("stable/") != string::npos) + Res += 2; + if (Path.find("frozen/") != string::npos) + Res += 2; + if (Path.find("/dists/") != string::npos) + Res += 4; + if (Path.find("/main/") != string::npos) + Res += 2; + if (Path.find("/contrib/") != string::npos) + Res += 2; + if (Path.find("/non-free/") != string::npos) + Res += 2; + if (Path.find("/non-US/") != string::npos) + Res += 2; + return Res; +} + /*}}}*/ +// DropRepeats - Drop repeated files resulting from symlinks /*{{{*/ +// --------------------------------------------------------------------- +/* Here we go and stat every file that we found and strip dup inodes. */ +bool DropRepeats(vector<string> &List) +{ + // Get a list of all the inodes + ino_t *Inodes = new ino_t[List.size()]; + for (unsigned int I = 0; I != List.size(); I++) + { + struct stat Buf; + if (stat(List[I].c_str(),&Buf) != 0) + _error->Errno("stat","Failed to stat %s",List[I].c_str()); + Inodes[I] = Buf.st_ino; + } + + // Look for dups + for (unsigned int I = 0; I != List.size(); I++) + { + for (unsigned int J = I+1; J < List.size(); J++) + { + // No match + if (Inodes[J] != Inodes[I]) + continue; + + // We score the two paths.. and erase one + int ScoreA = Score(List[I]); + int ScoreB = Score(List[J]); + if (ScoreA < ScoreB) + { + List[I] = string(); + break; + } + + List[J] = string(); + } + } + + // Wipe erased entries + for (unsigned int I = 0; I < List.size();) + { + if (List[I].empty() == false) + I++; + else + List.erase(List.begin()+I); + } + + return true; +} + /*}}}*/ +// ConvertToSourceList - Takes the path list and converts it /*{{{*/ +// --------------------------------------------------------------------- +/* This looks at each element and decides if it can be expressed using + dists/ form or if it requires an absolute specficiation. It also + strips the leading CDROM path from the paths. */ +bool ConvertToSourcelist(string CD,vector<string> &List) +{ + char S[300]; + sprintf(S,"binary-%s",_config->Find("Apt::Architecture").c_str()); + + sort(List.begin(),List.end()); + + // Convert to source list notation + for (vector<string>::iterator I = List.begin(); I != List.end(); I++) + { + // Strip the cdrom base path + *I = string(*I,CD.length()); + + // Too short to be a dists/ type + if ((*I).length() < strlen("dists/")) + continue; + + // Not a dists type. + if (stringcmp((*I).begin(),(*I).begin()+strlen("dists/"),"dists/") != 0) + continue; + + // Isolate the dist + string::size_type Slash = strlen("dists/"); + string::size_type Slash2 = (*I).find('/',Slash + 1); + if (Slash2 == string::npos || Slash2 + 2 >= (*I).length()) + continue; + string Dist = string(*I,Slash,Slash2 - Slash); + + // Isolate the component + Slash = (*I).find('/',Slash2+1); + if (Slash == string::npos || Slash + 2 >= (*I).length()) + continue; + string Comp = string(*I,Slash2+1,Slash - Slash2-1); + + // Verify the trailing binar - bit + Slash2 = (*I).find('/',Slash + 1); + if (Slash == string::npos) + continue; + string Binary = string(*I,Slash+1,Slash2 - Slash-1); + + if (Binary != S) + continue; + + *I = Dist + ' ' + Comp; + } + + // Collect similar entries + for (vector<string>::iterator I = List.begin(); I != List.end(); I++) + { + // Find a space.. + string::size_type Space = (*I).find(' '); + if (Space == string::npos) + continue; + + string Word1 = string(*I,0,Space); + for (vector<string>::iterator J = List.begin(); J != I; J++) + { + // Find a space.. + string::size_type Space2 = (*J).find(' '); + if (Space2 == string::npos) + continue; + + if (string(*J,0,Space2) != Word1) + continue; + + *J += string(*I,Space); + *I = string(); + } + } + + // Wipe erased entries + for (unsigned int I = 0; I < List.size();) + { + if (List[I].empty() == false) + I++; + else + List.erase(List.begin()+I); + } +} + /*}}}*/ + +// Prompt - Simple prompt /*{{{*/ +// --------------------------------------------------------------------- +/* */ +void Prompt(const char *Text) +{ + char C; + cout << Text << ' ' << flush; + read(STDIN_FILENO,&C,1); + if (C != '\n') + cout << endl; +} + /*}}}*/ +// PromptLine - Prompt for an input line /*{{{*/ +// --------------------------------------------------------------------- +/* */ +string PromptLine(const char *Text) +{ + cout << Text << ':' << endl; + + string Res; + getline(cin,Res); + return Res; +} + /*}}}*/ + +// DoAdd - Add a new CDROM /*{{{*/ +// --------------------------------------------------------------------- +/* */ +bool DoAdd(CommandLine &) +{ + // Startup + string CDROM = _config->FindDir("Acquire::cdrom::mount","/cdrom/"); + cout << "Using CD-ROM mount point " << CDROM << endl; + + // Read the database + Configuration Database; + string DFile = _config->FindFile("Dir::State::cdroms"); + if (FileExists(DFile) == true) + { + if (ReadConfigFile(Database,DFile) == false) + return _error->Error("Unable to read the cdrom database %s", + DFile.c_str()); + } + + // Unmount the CD and get the user to put in the one they want + if (_config->FindB("APT::CDROM::NoMount",false) == false) + { + cout << "Unmounting CD-ROM" << endl; + UnmountCdrom(CDROM); + + // Mount the new CDROM + Prompt("Please insert a CD-ROM and press any key"); + cout << "Mounting CD-ROM" << endl; + if (MountCdrom(CDROM) == false) + { + cout << "Failed to mount the cdrom." << endl; + return false; + } + } + + // Hash the CD to get an ID + cout << "Indentifying.. " << flush; + string ID; + if (IdentCdrom(CDROM,ID) == false) + return false; + cout << '[' << ID << ']' << endl; + + cout << "Scanning Disc for index files.. " << flush; + // Get the CD structure + vector<string> List; + string StartDir = SafeGetCWD(); + if (FindPackages(CDROM,List) == false) + return false; + chdir(StartDir.c_str()); + + // Fix up the list + DropBinaryArch(List); + DropRepeats(List); + cout << "Found " << List.size() << " package index files." << endl; + + if (List.size() == 0) + return _error->Error("Unable to locate any package files, perhaps this is not a debian CD-ROM"); + + // Check if the CD is in the database + string Name; + if (Database.Exists("CD::" + ID) == false || + _config->FindB("APT::CDROM::Rename",false) == true) + { + cout << "Please provide a name for this CD-ROM, such as 'Debian 2.1r1 Disk 1'"; + Name = PromptLine(""); + } + else + Name = Database.Find("CD::" + ID); + cout << "This Disc is called '" << Name << "'" << endl; + + // Copy the package files to the state directory + if (CopyPackages(CDROM,Name,List) == false) + return false; + + ConvertToSourcelist(CDROM,List); + + // Print the sourcelist entries + cout << "Source List entires for this Disc are:" << endl; + for (vector<string>::iterator I = List.begin(); I != List.end(); I++) + cout << "deb \"cdrom:" << Name << "/\" " << *I << endl; + + return true; +} + /*}}}*/ + +// ShowHelp - Show the help screen /*{{{*/ +// --------------------------------------------------------------------- +/* */ +int ShowHelp() +{ + cout << PACKAGE << ' ' << VERSION << " for " << ARCHITECTURE << + " compiled on " << __DATE__ << " " << __TIME__ << endl; + + cout << "Usage: apt-cdrom [options] command" << endl; + cout << endl; + cout << "apt-cdrom is a tool to add CDROM's to APT's source list. The " << endl; + cout << "CDROM mount point and device information is taken from apt.conf" << endl; + cout << "and /etc/fstab." << endl; + cout << endl; + cout << "Commands:" << endl; + cout << " add - Add a CDROM" << endl; + cout << endl; + cout << "Options:" << endl; + cout << " -h This help text" << endl; + cout << " -d CD-ROM mount point" << endl; + cout << " -r Rename a recognized CD-ROM" << endl; + cout << " -m No mounting" << endl; + cout << " -c=? Read this configuration file" << endl; + cout << " -o=? Set an arbitary configuration option, ie -o dir::cache=/tmp" << endl; + cout << "See fstab(5)" << endl; + return 100; +} + /*}}}*/ + +int main(int argc,const char *argv[]) +{ + CommandLine::Args Args[] = { + {'h',"help","help",0}, + {'d',"cdrom","Acquire::cdrom::mount",CommandLine::HasArg}, + {'r',"rename","APT::CDROM::Rename",0}, + {'m',"no-mount","APT::CDROM::NoMount",0}, + {'f',"fast","APT::CDROM::Fast",0}, + {'c',"config-file",0,CommandLine::ConfigFile}, + {'o',"option",0,CommandLine::ArbItem}, + {0,0,0,0}}; + CommandLine::Dispatch Cmds[] = { + {"add",&DoAdd}, + {0,0}}; + + // Parse the command line and initialize the package library + CommandLine CmdL(Args,_config); + if (pkgInitialize(*_config) == false || + CmdL.Parse(argc,argv) == false) + { + _error->DumpErrors(); + return 100; + } + + // See if the help should be shown + if (_config->FindB("help") == true || + CmdL.FileSize() == 0) + return ShowHelp(); + + // Match the operation + CmdL.DispatchArg(Cmds); + + // Print any errors or warnings found during parsing + if (_error->empty() == false) + { + bool Errors = _error->PendingError(); + _error->DumpErrors(); + return Errors == true?100:0; + } + + return 0; +} diff --git a/cmdline/apt-config.cc b/cmdline/apt-config.cc index 7dfb59192..81d49e5f3 100644 --- a/cmdline/apt-config.cc +++ b/cmdline/apt-config.cc @@ -1,6 +1,6 @@ // -*- mode: cpp; mode: fold -*- // Description /*{{{*/ -// $Id: apt-config.cc,v 1.1 1998/11/22 23:37:07 jgg Exp $ +// $Id: apt-config.cc,v 1.2 1998/11/27 01:52:57 jgg Exp $ /* ###################################################################### APT Config - Program to manipulate APT configuration files @@ -70,6 +70,8 @@ int main(int argc,const char *argv[]) {'c',"config-file",0,CommandLine::ConfigFile}, {'o',"option",0,CommandLine::ArbItem}, {0,0,0,0}}; + CommandLine::Dispatch Cmds[] = {{"shell",&DoShell}, + {0,0}}; // Parse the command line and initialize the package library CommandLine CmdL(Args,_config); @@ -84,29 +86,10 @@ int main(int argc,const char *argv[]) if (_config->FindB("help") == true || CmdL.FileSize() == 0) return ShowHelp(); - - // Match the operation - struct - { - const char *Match; - bool (*Handler)(CommandLine &); - } Map[] = {{"shell",&DoShell}, - {0,0}}; - int I; - for (I = 0; Map[I].Match != 0; I++) - { - if (strcmp(CmdL.FileList[0],Map[I].Match) == 0) - { - if (Map[I].Handler(CmdL) == false && _error->PendingError() == false) - _error->Error("Handler silently failed"); - break; - } - } - - // No matching name - if (Map[I].Match == 0) - _error->Error("Invalid operation %s", CmdL.FileList[0]); + // Match the operation + CmdL.DispatchArg(Cmds); + // Print any errors or warnings found during parsing if (_error->empty() == false) { diff --git a/cmdline/apt-get.cc b/cmdline/apt-get.cc index 42ef548ec..24fb36d46 100644 --- a/cmdline/apt-get.cc +++ b/cmdline/apt-get.cc @@ -1,6 +1,6 @@ // -*- mode: cpp; mode: fold -*- // Description /*{{{*/ -// $Id: apt-get.cc,v 1.19 1998/11/24 02:35:32 jgg Exp $ +// $Id: apt-get.cc,v 1.20 1998/11/27 01:52:58 jgg Exp $ /* ###################################################################### apt-get - Cover for dpkg @@ -79,10 +79,10 @@ bool YnPrompt() // --------------------------------------------------------------------- /* This prints out a string of space seperated words with a title and a two space indent line wraped to the current screen width. */ -void ShowList(ostream &out,string Title,string List) +bool ShowList(ostream &out,string Title,string List) { if (List.empty() == true) - return; + return true; // Acount for the leading space int ScreenWidth = ::ScreenWidth - 3; @@ -102,6 +102,7 @@ void ShowList(ostream &out,string Title,string List) out << " " << string(List,Start,End - Start) << endl; Start = End + 1; } + return false; } /*}}}*/ // ShowBroken - Debugging aide /*{{{*/ @@ -250,7 +251,7 @@ void ShowUpgraded(ostream &out,pkgDepCache &Dep) // ShowHold - Show held but changed packages /*{{{*/ // --------------------------------------------------------------------- /* */ -void ShowHold(ostream &out,pkgDepCache &Dep) +bool ShowHold(ostream &out,pkgDepCache &Dep) { pkgCache::PkgIterator I = Dep.PkgBegin(); string List; @@ -261,7 +262,7 @@ void ShowHold(ostream &out,pkgDepCache &Dep) List += string(I.Name()) + " "; } - ShowList(out,"The following held packages will be changed:",List); + return ShowList(out,"The following held packages will be changed:",List); } /*}}}*/ // ShowEssential - Show an essential package warning /*{{{*/ @@ -269,7 +270,7 @@ void ShowHold(ostream &out,pkgDepCache &Dep) /* This prints out a warning message that is not to be ignored. It shows all essential packages and their dependents that are to be removed. It is insanely risky to remove the dependents of an essential package! */ -void ShowEssential(ostream &out,pkgDepCache &Dep) +bool ShowEssential(ostream &out,pkgDepCache &Dep) { pkgCache::PkgIterator I = Dep.PkgBegin(); string List; @@ -317,11 +318,10 @@ void ShowEssential(ostream &out,pkgDepCache &Dep) } } + delete [] Added; if (List.empty() == false) out << "WARNING: The following essential packages will be removed" << endl; - ShowList(out,"This should NOT be done unless you know exactly what you are doing!",List); - - delete [] Added; + return ShowList(out,"This should NOT be done unless you know exactly what you are doing!",List); } /*}}}*/ // Stats - Show some statistics /*{{{*/ @@ -461,15 +461,17 @@ bool CacheFile::Open() happen and then calls the download routines */ bool InstallPackages(CacheFile &Cache,bool ShwKept,bool Ask = true) { + bool Fail = false; + // Show all the various warning indicators ShowDel(c1out,Cache); ShowNew(c1out,Cache); if (ShwKept == true) ShowKept(c1out,Cache); - ShowHold(c1out,Cache); + Fail |= ShowHold(c1out,Cache); if (_config->FindB("APT::Get::Show-Upgraded",false) == true) ShowUpgraded(c1out,Cache); - ShowEssential(c1out,Cache); + Fail |= ShowEssential(c1out,Cache); Stats(c1out,Cache); // Sanity check @@ -492,7 +494,9 @@ bool InstallPackages(CacheFile &Cache,bool ShwKept,bool Ask = true) // Create the text record parser pkgRecords Recs(Cache); - + if (_error->PendingError() == true) + return false; + // Lock the archive directory if (_config->FindB("Debug::NoLocking",false) == false) { @@ -542,16 +546,24 @@ bool InstallPackages(CacheFile &Cache,bool ShwKept,bool Ask = true) if (_error->PendingError() == true) return false; + // Fail safe check + if (_config->FindB("APT::Get::Assume-Yes",false) == true) + { + if (Fail == true && _config->FindB("APT::Get::Force-Yes",false) == false) + return _error->Error("There are problems and -y was used without --force-yes"); + } + // Prompt to continue if (Ask == true) - { - if (_config->FindI("quiet",0) < 2 || + { + if (_config->FindI("quiet",0) < 2 || _config->FindB("APT::Get::Assume-Yes",false) == false) - c2out << "Do you want to continue? [Y/n] " << flush; + c2out << "Do you want to continue? [Y/n] " << flush; + if (YnPrompt() == false) exit(1); } - + // Run it if (Fetcher.Run() == false) return false; @@ -975,6 +987,7 @@ void GetInitialize() _config->Set("APT::Get::Simulate",false); _config->Set("APT::Get::Assume-Yes",false); _config->Set("APT::Get::Fix-Broken",false); + _config->Set("APT::Get::Force-Yes",false); } /*}}}*/ // SigWinch - Window size change signal handler /*{{{*/ @@ -1010,10 +1023,20 @@ int main(int argc,const char *argv[]) {'m',"ignore-missing","APT::Get::Fix-Missing",0}, {0,"fix-missing","APT::Get::Fix-Missing",0}, {0,"ignore-hold","APT::Ingore-Hold",0}, - {0,"no-upgrade","APT::Get::no-upgrade",0}, + {0,"no-upgrade","APT::Get::no-upgrade",0}, + {0,"force-yes","APT::Get::force-yes",0}, {'c',"config-file",0,CommandLine::ConfigFile}, {'o',"option",0,CommandLine::ArbItem}, {0,0,0,0}}; + CommandLine::Dispatch Cmds[] = {{"update",&DoUpdate}, + {"upgrade",&DoUpgrade}, + {"install",&DoInstall}, + {"remove",&DoInstall}, + {"dist-upgrade",&DoDistUpgrade}, + {"dselect-upgrade",&DoDSelectUpgrade}, + {"clean",&DoClean}, + {"check",&DoCheck}, + {0,0}}; // Parse the command line and initialize the package library CommandLine CmdL(Args,_config); @@ -1044,33 +1067,7 @@ int main(int argc,const char *argv[]) SigWinch(0); // Match the operation - struct - { - const char *Match; - bool (*Handler)(CommandLine &); - } Map[] = {{"update",&DoUpdate}, - {"upgrade",&DoUpgrade}, - {"install",&DoInstall}, - {"remove",&DoInstall}, - {"dist-upgrade",&DoDistUpgrade}, - {"dselect-upgrade",&DoDSelectUpgrade}, - {"clean",&DoClean}, - {"check",&DoCheck}, - {0,0}}; - int I; - for (I = 0; Map[I].Match != 0; I++) - { - if (strcmp(CmdL.FileList[0],Map[I].Match) == 0) - { - if (Map[I].Handler(CmdL) == false && _error->PendingError() == false) - _error->Error("Handler silently failed"); - break; - } - } - - // No matching name - if (Map[I].Match == 0) - _error->Error("Invalid operation %s", CmdL.FileList[0]); + CmdL.DispatchArg(Cmds); // Print any errors or warnings found during parsing if (_error->empty() == false) diff --git a/cmdline/makefile b/cmdline/makefile index e52328440..c3a4d81d9 100644 --- a/cmdline/makefile +++ b/cmdline/makefile @@ -22,3 +22,9 @@ PROGRAM=apt-config SLIBS = -lapt-pkg SOURCE = apt-config.cc include $(PROGRAM_H) + +# The apt-cdrom program +PROGRAM=apt-cdrom +SLIBS = -lapt-pkg +SOURCE = apt-cdrom.cc +include $(PROGRAM_H) |