]> git.saurik.com Git - apt.git/blame - cmdline/apt-get.cc
Patchs for apt-cdrom
[apt.git] / cmdline / apt-get.cc
CommitLineData
0a8e3465
AL
1// -*- mode: cpp; mode: fold -*-
2// Description /*{{{*/
07801a6d 3// $Id: apt-get.cc,v 1.19 1998/11/24 02:35:32 jgg Exp $
0a8e3465
AL
4/* ######################################################################
5
6 apt-get - Cover for dpkg
7
8 This is an allout cover for dpkg implementing a safer front end. It is
9 based largely on libapt-pkg.
10
11 The syntax is different,
12 apt-get [opt] command [things]
13 Where command is:
14 update - Resyncronize the package files from their sources
15 upgrade - Smart-Download the newest versions of all packages
16 dselect-upgrade - Follows dselect's changes to the Status: field
17 and installes new and removes old packages
18 dist-upgrade - Powerfull upgrader designed to handle the issues with
19 a new distribution.
20 install - Download and install a given package (by name, not by .deb)
21 check - Update the package cache and check for broken packages
22 clean - Erase the .debs downloaded to /var/cache/apt/archives and
23 the partial dir too
24
25 ##################################################################### */
26 /*}}}*/
27// Include Files /*{{{*/
28#include <apt-pkg/error.h>
29#include <apt-pkg/cmndline.h>
30#include <apt-pkg/init.h>
31#include <apt-pkg/depcache.h>
32#include <apt-pkg/sourcelist.h>
33#include <apt-pkg/pkgcachegen.h>
34#include <apt-pkg/algorithms.h>
0919e3f9 35#include <apt-pkg/acquire-item.h>
03e39e59 36#include <apt-pkg/dpkgpm.h>
d38b7b3d 37#include <apt-pkg/dpkginit.h>
a6568219 38#include <strutl.h>
0a8e3465
AL
39
40#include <config.h>
41
0919e3f9
AL
42#include "acqprogress.h"
43
0a8e3465 44#include <fstream.h>
d7827aca
AL
45#include <termios.h>
46#include <sys/ioctl.h>
47#include <signal.h>
3e3221ba 48#include <stdio.h>
0a8e3465
AL
49 /*}}}*/
50
51ostream c0out;
52ostream c1out;
53ostream c2out;
54ofstream devnull("/dev/null");
55unsigned int ScreenWidth = 80;
56
a6568219
AL
57// YnPrompt - Yes No Prompt. /*{{{*/
58// ---------------------------------------------------------------------
59/* Returns true on a Yes.*/
60bool YnPrompt()
61{
62 if (_config->FindB("APT::Get::Assume-Yes",false) == true)
63 {
64 c2out << 'Y' << endl;
65 return true;
66 }
67
68 char C = 0;
69 char Jnk = 0;
70 read(STDIN_FILENO,&C,1);
71 while (C != '\n' && Jnk != '\n') read(STDIN_FILENO,&Jnk,1);
72
73 if (!(C == 'Y' || C == 'y' || C == '\n' || C == '\r'))
74 return false;
75 return true;
76}
77 /*}}}*/
0a8e3465
AL
78// ShowList - Show a list /*{{{*/
79// ---------------------------------------------------------------------
80/* This prints out a string of space seperated words with a title and
81 a two space indent line wraped to the current screen width. */
82void ShowList(ostream &out,string Title,string List)
83{
84 if (List.empty() == true)
85 return;
86
87 // Acount for the leading space
88 int ScreenWidth = ::ScreenWidth - 3;
89
90 out << Title << endl;
91 string::size_type Start = 0;
92 while (Start < List.size())
93 {
94 string::size_type End;
95 if (Start + ScreenWidth >= List.size())
96 End = List.size();
97 else
98 End = List.rfind(' ',Start+ScreenWidth);
99
100 if (End == string::npos || End < Start)
101 End = Start + ScreenWidth;
102 out << " " << string(List,Start,End - Start) << endl;
103 Start = End + 1;
104 }
105}
106 /*}}}*/
107// ShowBroken - Debugging aide /*{{{*/
108// ---------------------------------------------------------------------
109/* This prints out the names of all the packages that are broken along
110 with the name of each each broken dependency and a quite version
111 description. */
112void ShowBroken(ostream &out,pkgDepCache &Cache)
113{
30e1eab5 114 out << "Sorry, but the following packages have unmet dependencies:" << endl;
0a8e3465
AL
115 pkgCache::PkgIterator I = Cache.PkgBegin();
116 for (;I.end() != true; I++)
117 {
303a1703
AL
118 if (Cache[I].InstBroken() == false)
119 continue;
120
121 // Print out each package and the failed dependencies
122 out <<" " << I.Name() << ":";
123 int Indent = strlen(I.Name()) + 3;
124 bool First = true;
125 if (Cache[I].InstVerIter(Cache).end() == true)
0a8e3465 126 {
303a1703
AL
127 cout << endl;
128 continue;
129 }
130
30e1eab5 131 for (pkgCache::DepIterator D = Cache[I].InstVerIter(Cache).DependsList(); D.end() == false;)
303a1703 132 {
30e1eab5
AL
133 // Compute a single dependency element (glob or)
134 pkgCache::DepIterator Start;
135 pkgCache::DepIterator End;
136 D.GlobOr(Start,End);
137
138 if (Cache.IsImportantDep(End) == false ||
139 (Cache[End] & pkgDepCache::DepGInstall) == pkgDepCache::DepGInstall)
303a1703
AL
140 continue;
141
142 if (First == false)
143 for (int J = 0; J != Indent; J++)
144 out << ' ';
145 First = false;
cc718e9a 146
30e1eab5 147 cout << ' ' << End.DepType() << ": " << End.TargetPkg().Name();
303a1703
AL
148
149 // Show a quick summary of the version requirements
30e1eab5
AL
150 if (End.TargetVer() != 0)
151 out << " (" << End.CompType() << " " << End.TargetVer() <<
303a1703
AL
152 ")";
153
154 /* Show a summary of the target package if possible. In the case
155 of virtual packages we show nothing */
156
30e1eab5 157 pkgCache::PkgIterator Targ = End.TargetPkg();
303a1703 158 if (Targ->ProvidesList == 0)
0a8e3465 159 {
303a1703
AL
160 out << " but ";
161 pkgCache::VerIterator Ver = Cache[Targ].InstVerIter(Cache);
162 if (Ver.end() == false)
163 out << Ver.VerStr() << " is installed";
0a8e3465 164 else
7e798dd7 165 {
303a1703
AL
166 if (Cache[Targ].CandidateVerIter(Cache).end() == true)
167 {
168 if (Targ->ProvidesList == 0)
169 out << "it is not installable";
170 else
171 out << "it is a virtual package";
172 }
7e798dd7
AL
173 else
174 out << "it is not installed";
303a1703
AL
175 }
176 }
177
178 out << endl;
179 }
0a8e3465
AL
180 }
181}
182 /*}}}*/
183// ShowNew - Show packages to newly install /*{{{*/
184// ---------------------------------------------------------------------
185/* */
186void ShowNew(ostream &out,pkgDepCache &Dep)
187{
188 /* Print out a list of packages that are going to be removed extra
189 to what the user asked */
190 pkgCache::PkgIterator I = Dep.PkgBegin();
191 string List;
192 for (;I.end() != true; I++)
193 if (Dep[I].NewInstall() == true)
194 List += string(I.Name()) + " ";
195 ShowList(out,"The following NEW packages will be installed:",List);
196}
197 /*}}}*/
198// ShowDel - Show packages to delete /*{{{*/
199// ---------------------------------------------------------------------
200/* */
201void ShowDel(ostream &out,pkgDepCache &Dep)
202{
203 /* Print out a list of packages that are going to be removed extra
204 to what the user asked */
205 pkgCache::PkgIterator I = Dep.PkgBegin();
206 string List;
207 for (;I.end() != true; I++)
208 if (Dep[I].Delete() == true)
209 List += string(I.Name()) + " ";
210 ShowList(out,"The following packages will be REMOVED:",List);
211}
212 /*}}}*/
213// ShowKept - Show kept packages /*{{{*/
214// ---------------------------------------------------------------------
215/* */
216void ShowKept(ostream &out,pkgDepCache &Dep)
217{
218 pkgCache::PkgIterator I = Dep.PkgBegin();
219 string List;
220 for (;I.end() != true; I++)
221 {
222 // Not interesting
223 if (Dep[I].Upgrade() == true || Dep[I].Upgradable() == false ||
224 I->CurrentVer == 0 || Dep[I].Delete() == true)
225 continue;
226
227 List += string(I.Name()) + " ";
228 }
229 ShowList(out,"The following packages have been kept back",List);
230}
231 /*}}}*/
232// ShowUpgraded - Show upgraded packages /*{{{*/
233// ---------------------------------------------------------------------
234/* */
235void ShowUpgraded(ostream &out,pkgDepCache &Dep)
236{
237 pkgCache::PkgIterator I = Dep.PkgBegin();
238 string List;
239 for (;I.end() != true; I++)
240 {
241 // Not interesting
242 if (Dep[I].Upgrade() == false || Dep[I].NewInstall() == true)
243 continue;
244
245 List += string(I.Name()) + " ";
246 }
247 ShowList(out,"The following packages will be upgraded",List);
248}
249 /*}}}*/
250// ShowHold - Show held but changed packages /*{{{*/
251// ---------------------------------------------------------------------
252/* */
253void ShowHold(ostream &out,pkgDepCache &Dep)
254{
255 pkgCache::PkgIterator I = Dep.PkgBegin();
256 string List;
257 for (;I.end() != true; I++)
258 {
259 if (Dep[I].InstallVer != (pkgCache::Version *)I.CurrentVer() &&
260 I->SelectedState == pkgCache::State::Hold)
261 List += string(I.Name()) + " ";
262 }
263
264 ShowList(out,"The following held packages will be changed:",List);
265}
266 /*}}}*/
267// ShowEssential - Show an essential package warning /*{{{*/
268// ---------------------------------------------------------------------
269/* This prints out a warning message that is not to be ignored. It shows
270 all essential packages and their dependents that are to be removed.
271 It is insanely risky to remove the dependents of an essential package! */
272void ShowEssential(ostream &out,pkgDepCache &Dep)
273{
274 pkgCache::PkgIterator I = Dep.PkgBegin();
275 string List;
276 bool *Added = new bool[Dep.HeaderP->PackageCount];
93641593 277 for (unsigned int I = 0; I != Dep.HeaderP->PackageCount; I++)
0a8e3465
AL
278 Added[I] = false;
279
280 for (;I.end() != true; I++)
281 {
282 if ((I->Flags & pkgCache::Flag::Essential) != pkgCache::Flag::Essential)
283 continue;
284
285 // The essential package is being removed
286 if (Dep[I].Delete() == true)
287 {
288 if (Added[I->ID] == false)
289 {
290 Added[I->ID] = true;
291 List += string(I.Name()) + " ";
292 }
293 }
294
295 if (I->CurrentVer == 0)
296 continue;
297
298 // Print out any essential package depenendents that are to be removed
299 for (pkgDepCache::DepIterator D = I.CurrentVer().DependsList(); D.end() == false; D++)
300 {
3e3221ba
AL
301 // Skip everything but depends
302 if (D->Type != pkgCache::Dep::PreDepends &&
303 D->Type != pkgCache::Dep::Depends)
304 continue;
305
0a8e3465
AL
306 pkgCache::PkgIterator P = D.SmartTargetPkg();
307 if (Dep[P].Delete() == true)
308 {
309 if (Added[P->ID] == true)
310 continue;
311 Added[P->ID] = true;
3e3221ba
AL
312
313 char S[300];
314 sprintf(S,"%s (due to %s) ",P.Name(),I.Name());
315 List += S;
0a8e3465
AL
316 }
317 }
318 }
319
320 if (List.empty() == false)
321 out << "WARNING: The following essential packages will be removed" << endl;
322 ShowList(out,"This should NOT be done unless you know exactly what you are doing!",List);
323
324 delete [] Added;
325}
326 /*}}}*/
327// Stats - Show some statistics /*{{{*/
328// ---------------------------------------------------------------------
329/* */
330void Stats(ostream &out,pkgDepCache &Dep)
331{
332 unsigned long Upgrade = 0;
333 unsigned long Install = 0;
334 for (pkgCache::PkgIterator I = Dep.PkgBegin(); I.end() == false; I++)
335 {
336 if (Dep[I].NewInstall() == true)
337 Install++;
338 else
339 if (Dep[I].Upgrade() == true)
340 Upgrade++;
341 }
342
343 out << Upgrade << " packages upgraded, " <<
344 Install << " newly installed, " <<
345 Dep.DelCount() << " to remove and " <<
346 Dep.KeepCount() << " not upgraded." << endl;
347
348 if (Dep.BadCount() != 0)
349 out << Dep.BadCount() << " packages not fully installed or removed." << endl;
350}
351 /*}}}*/
352
353// class CacheFile - Cover class for some dependency cache functions /*{{{*/
354// ---------------------------------------------------------------------
355/* */
356class CacheFile
357{
358 public:
359
360 FileFd *File;
361 MMap *Map;
362 pkgDepCache *Cache;
d38b7b3d 363 pkgDpkgLock Lock;
0a8e3465
AL
364
365 inline operator pkgDepCache &() {return *Cache;};
366 inline pkgDepCache *operator ->() {return Cache;};
367 inline pkgDepCache &operator *() {return *Cache;};
368
369 bool Open();
370 CacheFile() : File(0), Map(0), Cache(0) {};
371 ~CacheFile()
372 {
373 delete Cache;
374 delete Map;
375 delete File;
376 }
377};
378 /*}}}*/
379// CacheFile::Open - Open the cache file /*{{{*/
380// ---------------------------------------------------------------------
381/* This routine generates the caches and then opens the dependency cache
382 and verifies that the system is OK. */
383bool CacheFile::Open()
384{
d38b7b3d
AL
385 if (_error->PendingError() == true)
386 return false;
387
0a8e3465
AL
388 // Create a progress class
389 OpTextProgress Progress(*_config);
390
391 // Read the source list
392 pkgSourceList List;
393 if (List.ReadMainList() == false)
394 return _error->Error("The list of sources could not be read.");
395
396 // Build all of the caches
397 pkgMakeStatusCache(List,Progress);
398 if (_error->PendingError() == true)
399 return _error->Error("The package lists or status file could not be parsed or opened.");
400
401 Progress.Done();
402
403 // Open the cache file
303a1703 404 File = new FileFd(_config->FindFile("Dir::Cache::pkgcache"),FileFd::ReadOnly);
0a8e3465
AL
405 if (_error->PendingError() == true)
406 return false;
407
408 Map = new MMap(*File,MMap::Public | MMap::ReadOnly);
409 if (_error->PendingError() == true)
410 return false;
411
412 Cache = new pkgDepCache(*Map,Progress);
413 if (_error->PendingError() == true)
414 return false;
415
416 Progress.Done();
417
418 // Check that the system is OK
419 if (Cache->DelCount() != 0 || Cache->InstCount() != 0)
420 return _error->Error("Internal Error, non-zero counts");
421
422 // Apply corrections for half-installed packages
423 if (pkgApplyStatus(*Cache) == false)
424 return false;
425
426 // Nothing is broken
427 if (Cache->BrokenCount() == 0)
428 return true;
429
430 // Attempt to fix broken things
431 if (_config->FindB("APT::Get::Fix-Broken",false) == true)
432 {
433 c1out << "Correcting dependencies..." << flush;
434 if (pkgFixBroken(*Cache) == false || Cache->BrokenCount() != 0)
435 {
436 c1out << " failed." << endl;
437 ShowBroken(c1out,*this);
438
439 return _error->Error("Unable to correct dependencies");
440 }
7e798dd7
AL
441 if (pkgMinimizeUpgrade(*Cache) == false)
442 return _error->Error("Unable to minimize the upgrade set");
0a8e3465
AL
443
444 c1out << " Done" << endl;
445 }
446 else
447 {
448 c1out << "You might want to run `apt-get -f install' to correct these." << endl;
449 ShowBroken(c1out,*this);
450
451 return _error->Error("Unmet dependencies. Try using -f.");
452 }
453
454 return true;
455}
456 /*}}}*/
457
458// InstallPackages - Actually download and install the packages /*{{{*/
459// ---------------------------------------------------------------------
460/* This displays the informative messages describing what is going to
461 happen and then calls the download routines */
d38b7b3d 462bool InstallPackages(CacheFile &Cache,bool ShwKept,bool Ask = true)
0a8e3465 463{
a6568219 464 // Show all the various warning indicators
0a8e3465
AL
465 ShowDel(c1out,Cache);
466 ShowNew(c1out,Cache);
467 if (ShwKept == true)
468 ShowKept(c1out,Cache);
469 ShowHold(c1out,Cache);
470 if (_config->FindB("APT::Get::Show-Upgraded",false) == true)
471 ShowUpgraded(c1out,Cache);
472 ShowEssential(c1out,Cache);
473 Stats(c1out,Cache);
474
475 // Sanity check
d38b7b3d 476 if (Cache->BrokenCount() != 0)
0a8e3465
AL
477 {
478 ShowBroken(c1out,Cache);
479 return _error->Error("Internal Error, InstallPackages was called with broken packages!");
480 }
481
d38b7b3d
AL
482 if (Cache->DelCount() == 0 && Cache->InstCount() == 0 &&
483 Cache->BadCount() == 0)
0a8e3465 484 return true;
03e39e59
AL
485
486 // Run the simulator ..
487 if (_config->FindB("APT::Get::Simulate") == true)
488 {
489 pkgSimulate PM(Cache);
490 return PM.DoInstall();
491 }
492
493 // Create the text record parser
494 pkgRecords Recs(Cache);
d38b7b3d
AL
495
496 // Lock the archive directory
497 if (_config->FindB("Debug::NoLocking",false) == false)
498 {
499 FileFd Lock(GetLock(_config->FindDir("Dir::Cache::Archives") + "lock"));
500 if (_error->PendingError() == true)
501 return _error->Error("Unable to lock the download directory");
502 }
03e39e59
AL
503
504 // Create the download object
505 AcqTextStatus Stat(ScreenWidth,_config->FindI("quiet",0));
506 pkgAcquire Fetcher(&Stat);
507
508 // Read the source list
509 pkgSourceList List;
510 if (List.ReadMainList() == false)
511 return _error->Error("The list of sources could not be read.");
512
513 // Create the package manager and prepare to download
30e1eab5 514 pkgDPkgPM PM(Cache);
03e39e59
AL
515 if (PM.GetArchives(&Fetcher,&List,&Recs) == false)
516 return false;
517
7a1b1f8b 518 // Display statistics
a6568219
AL
519 unsigned long FetchBytes = Fetcher.FetchNeeded();
520 unsigned long DebBytes = Fetcher.TotalNeeded();
d38b7b3d
AL
521 if (DebBytes != Cache->DebSize())
522 {
523 c0out << DebBytes << ',' << Cache->DebSize() << endl;
a6568219 524 c0out << "How odd.. The sizes didn't match, email apt@packages.debian.org" << endl;
d38b7b3d
AL
525 }
526
7a1b1f8b 527 // Number of bytes
a6568219
AL
528 c1out << "Need to get ";
529 if (DebBytes != FetchBytes)
530 c1out << SizeToStr(FetchBytes) << '/' << SizeToStr(DebBytes);
531 else
532 c1out << SizeToStr(DebBytes);
533
534 c1out << " of archives. After unpacking ";
535
7a1b1f8b 536 // Size delta
d38b7b3d
AL
537 if (Cache->UsrSize() >= 0)
538 c1out << SizeToStr(Cache->UsrSize()) << " will be used." << endl;
a6568219 539 else
d38b7b3d 540 c1out << SizeToStr(-1*Cache->UsrSize()) << " will be freed." << endl;
a6568219
AL
541
542 if (_error->PendingError() == true)
543 return false;
544
7a1b1f8b 545 // Prompt to continue
a6568219 546 if (Ask == true)
e331f6ed 547 {
a6568219
AL
548 if (_config->FindI("quiet",0) < 2 ||
549 _config->FindB("APT::Get::Assume-Yes",false) == false)
550 c2out << "Do you want to continue? [Y/n] " << flush;
551 if (YnPrompt() == false)
552 exit(1);
553 }
554
03e39e59
AL
555 // Run it
556 if (Fetcher.Run() == false)
557 return false;
30e1eab5
AL
558
559 // Print out errors
560 bool Failed = false;
561 for (pkgAcquire::Item **I = Fetcher.ItemsBegin(); I != Fetcher.ItemsEnd(); I++)
562 {
563 if ((*I)->Status == pkgAcquire::Item::StatDone &&
564 (*I)->Complete == true)
565 continue;
566
567 cerr << "Failed to fetch " << (*I)->Describe() << endl;
568 cerr << " " << (*I)->ErrorText << endl;
569 Failed = true;
570 }
03e39e59 571
30e1eab5
AL
572 if (Failed == true && _config->FindB("APT::Fix-Missing",false) == false)
573 return _error->Error("Unable to fetch some archives, maybe try with --fix-missing?");
574
575 // Try to deal with missing package files
d38b7b3d 576 if (PM.FixMissing() == false)
30e1eab5
AL
577 {
578 cerr << "Unable to correct missing packages." << endl;
579 return _error->Error("Aborting Install.");
d38b7b3d 580 }
30e1eab5 581
d38b7b3d 582 Cache.Lock.Close();
30e1eab5 583 return PM.DoInstall();
0a8e3465
AL
584}
585 /*}}}*/
586
587// DoUpdate - Update the package lists /*{{{*/
588// ---------------------------------------------------------------------
589/* */
0919e3f9 590bool DoUpdate(CommandLine &)
0a8e3465 591{
0919e3f9
AL
592 // Get the source list
593 pkgSourceList List;
594 if (List.ReadMainList() == false)
595 return false;
596
d38b7b3d
AL
597 // Lock the list directory
598 if (_config->FindB("Debug::NoLocking",false) == false)
599 {
600 FileFd Lock(GetLock(_config->FindDir("Dir::State::Lists") + "lock"));
601 if (_error->PendingError() == true)
602 return _error->Error("Unable to lock the list directory");
603 }
604
0919e3f9
AL
605 // Create the download object
606 AcqTextStatus Stat(ScreenWidth,_config->FindI("quiet",0));
607 pkgAcquire Fetcher(&Stat);
608
609 // Populate it with the source selection
610 pkgSourceList::const_iterator I;
611 for (I = List.begin(); I != List.end(); I++)
612 {
613 new pkgAcqIndex(&Fetcher,I);
614 if (_error->PendingError() == true)
615 return false;
616 }
617
618 // Run it
619 if (Fetcher.Run() == false)
620 return false;
621
7a7fa5f0
AL
622 // Clean out any old list files
623 if (Fetcher.Clean(_config->FindDir("Dir::State::lists")) == false ||
624 Fetcher.Clean(_config->FindDir("Dir::State::lists") + "partial/") == false)
625 return false;
626
0919e3f9
AL
627 // Prepare the cache.
628 CacheFile Cache;
629 if (Cache.Open() == false)
630 return false;
631
632 return true;
0a8e3465
AL
633}
634 /*}}}*/
635// DoUpgrade - Upgrade all packages /*{{{*/
636// ---------------------------------------------------------------------
637/* Upgrade all packages without installing new packages or erasing old
638 packages */
639bool DoUpgrade(CommandLine &CmdL)
640{
641 CacheFile Cache;
642 if (Cache.Open() == false)
643 return false;
644
645 // Do the upgrade
0a8e3465
AL
646 if (pkgAllUpgrade(Cache) == false)
647 {
648 ShowBroken(c1out,Cache);
649 return _error->Error("Internal Error, AllUpgrade broke stuff");
650 }
651
652 return InstallPackages(Cache,true);
653}
654 /*}}}*/
655// DoInstall - Install packages from the command line /*{{{*/
656// ---------------------------------------------------------------------
657/* Install named packages */
658bool DoInstall(CommandLine &CmdL)
659{
660 CacheFile Cache;
661 if (Cache.Open() == false)
662 return false;
663
a6568219
AL
664 unsigned int ExpectedInst = 0;
665 unsigned int Packages = 0;
0a8e3465
AL
666 pkgProblemResolver Fix(Cache);
667
303a1703
AL
668 bool DefRemove = false;
669 if (strcasecmp(CmdL.FileList[0],"remove") == 0)
670 DefRemove = true;
671
0a8e3465
AL
672 for (const char **I = CmdL.FileList + 1; *I != 0; I++)
673 {
674 // Duplicate the string
675 unsigned int Length = strlen(*I);
676 char S[300];
677 if (Length >= sizeof(S))
678 continue;
679 strcpy(S,*I);
680
681 // See if we are removing the package
303a1703 682 bool Remove = DefRemove;
2c3bc8bb 683 if (Cache->FindPkg(S).end() == true)
0a8e3465 684 {
2c3bc8bb
AL
685 // Handle an optional end tag indicating what to do
686 if (S[Length - 1] == '-')
687 {
688 Remove = true;
689 S[--Length] = 0;
690 }
691 if (S[Length - 1] == '+')
692 {
693 Remove = false;
694 S[--Length] = 0;
695 }
303a1703 696 }
0a8e3465
AL
697
698 // Locate the package
699 pkgCache::PkgIterator Pkg = Cache->FindPkg(S);
303a1703 700 Packages++;
0a8e3465
AL
701 if (Pkg.end() == true)
702 return _error->Error("Couldn't find package %s",S);
703
2c3bc8bb
AL
704 // Handle the no-upgrade case
705 if (_config->FindB("APT::Get::no-upgrade",false) == true &&
706 Pkg->CurrentVer != 0)
707 {
708 c1out << "Skipping " << Pkg.Name() << ", it is already installed and no-upgrade is set." << endl;
709 continue;
710 }
711
0a8e3465
AL
712 // Check if there is something new to install
713 pkgDepCache::StateCache &State = (*Cache)[Pkg];
714 if (State.CandidateVer == 0)
303a1703
AL
715 {
716 if (Pkg->ProvidesList != 0)
717 {
718 c1out << "Package " << S << " is a virtual package provided by:" << endl;
719
720 pkgCache::PrvIterator I = Pkg.ProvidesList();
721 for (; I.end() == false; I++)
722 {
723 pkgCache::PkgIterator Pkg = I.OwnerPkg();
724
725 if ((*Cache)[Pkg].CandidateVerIter(*Cache) == I.OwnerVer())
726 c1out << " " << Pkg.Name() << " " << I.OwnerVer().VerStr() << endl;
727
728 if ((*Cache)[Pkg].InstVerIter(*Cache) == I.OwnerVer())
729 c1out << " " << Pkg.Name() << " " << I.OwnerVer().VerStr() <<
730 " [Installed]"<< endl;
731 }
732 c1out << "You should explicly select one to install." << endl;
733 }
734 else
735 {
736 c1out << "Package " << S << " has no available version, but exists in the database." << endl;
737 c1out << "This typically means that the package was mentioned in a dependency and " << endl;
738 c1out << "never uploaded, or that it is an obsolete package." << endl;
07801a6d
AL
739
740 string List;
741 pkgCache::DepIterator Dep = Pkg.RevDependsList();
742 for (; Dep.end() == false; Dep++)
743 {
744 if (Dep->Type != pkgCache::Dep::Replaces)
745 continue;
746 List += string(Dep.ParentPkg().Name()) + " ";
747 }
748 ShowList(c1out,"However the following packages replace it:",List);
303a1703
AL
749 }
750
0a8e3465 751 return _error->Error("Package %s has no installation candidate",S);
303a1703 752 }
0a8e3465
AL
753
754 Fix.Protect(Pkg);
755 if (Remove == true)
756 {
303a1703 757 Fix.Remove(Pkg);
0a8e3465
AL
758 Cache->MarkDelete(Pkg);
759 continue;
760 }
761
762 // Install it
763 Cache->MarkInstall(Pkg,false);
764 if (State.Install() == false)
765 c1out << "Sorry, " << S << " is already the newest version" << endl;
766 else
767 ExpectedInst++;
768
769 // Install it with autoinstalling enabled.
770 if (State.InstBroken() == true)
771 Cache->MarkInstall(Pkg,true);
772 }
773
774 // Call the scored problem resolver
303a1703 775 Fix.InstallProtect();
0a8e3465
AL
776 if (Fix.Resolve(true) == false)
777 _error->Discard();
778
779 // Now we check the state of the packages,
780 if (Cache->BrokenCount() != 0)
781 {
303a1703
AL
782 c1out << "Some packages could not be installed. This may mean that you have" << endl;
783 c1out << "requested an impossible situation or if you are using the unstable" << endl;
784 c1out << "distribution that some required packages have not yet been created" << endl;
785 c1out << "or been moved out of Incoming." << endl;
786 if (Packages == 1)
787 {
788 c1out << endl;
789 c1out << "Since you only requested a single operation it is extremely likely that" << endl;
790 c1out << "the package is simply not installable and a bug report against" << endl;
791 c1out << "that package should be filed." << endl;
792 }
793
794 c1out << "The following information may help to resolve the situation:" << endl;
795 c1out << endl;
0a8e3465
AL
796 ShowBroken(c1out,Cache);
797 return _error->Error("Sorry, broken packages");
798 }
799
800 /* Print out a list of packages that are going to be installed extra
801 to what the user asked */
802 if (Cache->InstCount() != ExpectedInst)
803 {
804 string List;
805 pkgCache::PkgIterator I = Cache->PkgBegin();
806 for (;I.end() != true; I++)
807 {
808 if ((*Cache)[I].Install() == false)
809 continue;
810
811 const char **J;
812 for (J = CmdL.FileList + 1; *J != 0; J++)
813 if (strcmp(*J,I.Name()) == 0)
814 break;
815
816 if (*J == 0)
817 List += string(I.Name()) + " ";
818 }
819
820 ShowList(c1out,"The following extra packages will be installed:",List);
821 }
822
03e39e59 823 // See if we need to prompt
2c3bc8bb 824 if (Cache->InstCount() == ExpectedInst && Cache->DelCount() == 0)
2c3bc8bb 825 return InstallPackages(Cache,false,false);
2c3bc8bb 826
03e39e59 827 return InstallPackages(Cache,false);
0a8e3465
AL
828}
829 /*}}}*/
830// DoDistUpgrade - Automatic smart upgrader /*{{{*/
831// ---------------------------------------------------------------------
832/* Intelligent upgrader that will install and remove packages at will */
833bool DoDistUpgrade(CommandLine &CmdL)
834{
835 CacheFile Cache;
836 if (Cache.Open() == false)
837 return false;
838
839 c0out << "Calculating Upgrade... " << flush;
840 if (pkgDistUpgrade(*Cache) == false)
841 {
842 c0out << "Failed" << endl;
843 ShowBroken(c1out,Cache);
844 return false;
845 }
846
847 c0out << "Done" << endl;
848
849 return InstallPackages(Cache,true);
850}
851 /*}}}*/
852// DoDSelectUpgrade - Do an upgrade by following dselects selections /*{{{*/
853// ---------------------------------------------------------------------
854/* Follows dselect's selections */
855bool DoDSelectUpgrade(CommandLine &CmdL)
856{
857 CacheFile Cache;
858 if (Cache.Open() == false)
859 return false;
860
861 // Install everything with the install flag set
862 pkgCache::PkgIterator I = Cache->PkgBegin();
863 for (;I.end() != true; I++)
864 {
865 /* Install the package only if it is a new install, the autoupgrader
866 will deal with the rest */
867 if (I->SelectedState == pkgCache::State::Install)
868 Cache->MarkInstall(I,false);
869 }
870
871 /* Now install their deps too, if we do this above then order of
872 the status file is significant for | groups */
873 for (I = Cache->PkgBegin();I.end() != true; I++)
874 {
875 /* Install the package only if it is a new install, the autoupgrader
876 will deal with the rest */
877 if (I->SelectedState == pkgCache::State::Install)
878 Cache->MarkInstall(I);
879 }
880
881 // Apply erasures now, they override everything else.
882 for (I = Cache->PkgBegin();I.end() != true; I++)
883 {
884 // Remove packages
885 if (I->SelectedState == pkgCache::State::DeInstall ||
886 I->SelectedState == pkgCache::State::Purge)
887 Cache->MarkDelete(I);
888 }
889
890 /* Use updates smart upgrade to do the rest, it will automatically
891 ignore held items */
892 if (pkgAllUpgrade(Cache) == false)
893 {
894 ShowBroken(c1out,Cache);
895 return _error->Error("Internal Error, AllUpgrade broke stuff");
896 }
897
898 return InstallPackages(Cache,false);
899}
900 /*}}}*/
901// DoClean - Remove download archives /*{{{*/
902// ---------------------------------------------------------------------
903/* */
904bool DoClean(CommandLine &CmdL)
905{
7a1b1f8b
AL
906 pkgAcquire Fetcher;
907 Fetcher.Clean(_config->FindDir("Dir::Cache::archives"));
908 Fetcher.Clean(_config->FindDir("Dir::Cache::archives") + "partial/");
0a8e3465
AL
909 return true;
910}
911 /*}}}*/
912// DoCheck - Perform the check operation /*{{{*/
913// ---------------------------------------------------------------------
914/* Opening automatically checks the system, this command is mostly used
915 for debugging */
916bool DoCheck(CommandLine &CmdL)
917{
918 CacheFile Cache;
919 Cache.Open();
920
921 return true;
922}
923 /*}}}*/
924
925// ShowHelp - Show a help screen /*{{{*/
926// ---------------------------------------------------------------------
927/* */
928int ShowHelp()
929{
930 cout << PACKAGE << ' ' << VERSION << " for " << ARCHITECTURE <<
931 " compiled on " << __DATE__ << " " << __TIME__ << endl;
932
933 cout << "Usage: apt-get [options] command" << endl;
934 cout << " apt-get [options] install pkg1 [pkg2 ...]" << endl;
935 cout << endl;
936 cout << "apt-get is a simple command line interface for downloading and" << endl;
937 cout << "installing packages. The most frequently used commands are update" << endl;
938 cout << "and install." << endl;
939 cout << endl;
940 cout << "Commands:" << endl;
941 cout << " update - Retrieve new lists of packages" << endl;
942 cout << " upgrade - Perform an upgrade" << endl;
943 cout << " install - Install new packages (pkg is libc6 not libc6.deb)" << endl;
303a1703 944 cout << " remove - Remove packages" << endl;
0a8e3465
AL
945 cout << " dist-upgrade - Distribution upgrade, see apt-get(8)" << endl;
946 cout << " dselect-upgrade - Follow dselect selections" << endl;
947 cout << " clean - Erase downloaded archive files" << endl;
948 cout << " check - Verify that there are no broken dependencies" << endl;
949 cout << endl;
950 cout << "Options:" << endl;
c217f42a
AL
951 cout << " -h This help text." << endl;
952 cout << " -q Loggable output - no progress indicator" << endl;
0a8e3465
AL
953 cout << " -qq No output except for errors" << endl;
954 cout << " -d Download only - do NOT install or unpack archives" << endl;
955 cout << " -s No-act. Perform ordering simulation" << endl;
956 cout << " -y Assume Yes to all queries and do not prompt" << endl;
957 cout << " -f Attempt to continue if the integrity check fails" << endl;
958 cout << " -m Attempt to continue if archives are unlocatable" << endl;
959 cout << " -u Show a list of upgraded packages as well" << endl;
960 cout << " -c=? Read this configuration file" << endl;
961 cout << " -o=? Set an arbitary configuration option, ie -o dir::cache=/tmp" << endl;
962 cout << "See the apt-get(8), sources.list(8) and apt.conf(8) manual" << endl;
963 cout << "pages for more information." << endl;
964 return 100;
965}
966 /*}}}*/
967// GetInitialize - Initialize things for apt-get /*{{{*/
968// ---------------------------------------------------------------------
969/* */
970void GetInitialize()
971{
972 _config->Set("quiet",0);
973 _config->Set("help",false);
974 _config->Set("APT::Get::Download-Only",false);
975 _config->Set("APT::Get::Simulate",false);
976 _config->Set("APT::Get::Assume-Yes",false);
977 _config->Set("APT::Get::Fix-Broken",false);
978}
979 /*}}}*/
d7827aca
AL
980// SigWinch - Window size change signal handler /*{{{*/
981// ---------------------------------------------------------------------
982/* */
983void SigWinch(int)
984{
985 // Riped from GNU ls
986#ifdef TIOCGWINSZ
987 struct winsize ws;
988
989 if (ioctl(1, TIOCGWINSZ, &ws) != -1 && ws.ws_col >= 5)
990 ScreenWidth = ws.ws_col - 1;
991#endif
992}
993 /*}}}*/
0a8e3465
AL
994
995int main(int argc,const char *argv[])
996{
997 CommandLine::Args Args[] = {
998 {'h',"help","help",0},
999 {'q',"quiet","quiet",CommandLine::IntLevel},
1000 {'q',"silent","quiet",CommandLine::IntLevel},
1001 {'d',"download-only","APT::Get::Download-Only",0},
1002 {'s',"simulate","APT::Get::Simulate",0},
1003 {'s',"just-print","APT::Get::Simulate",0},
1004 {'s',"recon","APT::Get::Simulate",0},
1005 {'s',"no-act","APT::Get::Simulate",0},
1006 {'y',"yes","APT::Get::Assume-Yes",0},
1007 {'y',"assume-yes","APT::Get::Assume-Yes",0},
1008 {'f',"fix-broken","APT::Get::Fix-Broken",0},
1009 {'u',"show-upgraded","APT::Get::Show-Upgraded",0},
30e1eab5
AL
1010 {'m',"ignore-missing","APT::Get::Fix-Missing",0},
1011 {0,"fix-missing","APT::Get::Fix-Missing",0},
c88edf1d 1012 {0,"ignore-hold","APT::Ingore-Hold",0},
2c3bc8bb 1013 {0,"no-upgrade","APT::Get::no-upgrade",0},
0a8e3465
AL
1014 {'c',"config-file",0,CommandLine::ConfigFile},
1015 {'o',"option",0,CommandLine::ArbItem},
1016 {0,0,0,0}};
1017
1018 // Parse the command line and initialize the package library
1019 CommandLine CmdL(Args,_config);
1020 if (pkgInitialize(*_config) == false ||
1021 CmdL.Parse(argc,argv) == false)
1022 {
1023 _error->DumpErrors();
1024 return 100;
1025 }
1026
1027 // See if the help should be shown
1028 if (_config->FindB("help") == true ||
1029 CmdL.FileSize() == 0)
1030 return ShowHelp();
1031
1032 // Setup the output streams
1033 c0out.rdbuf(cout.rdbuf());
1034 c1out.rdbuf(cout.rdbuf());
1035 c2out.rdbuf(cout.rdbuf());
1036 if (_config->FindI("quiet",0) > 0)
1037 c0out.rdbuf(devnull.rdbuf());
1038 if (_config->FindI("quiet",0) > 1)
1039 c1out.rdbuf(devnull.rdbuf());
d7827aca
AL
1040
1041 // Setup the signals
1042 signal(SIGPIPE,SIG_IGN);
1043 signal(SIGWINCH,SigWinch);
1044 SigWinch(0);
0a8e3465
AL
1045
1046 // Match the operation
1047 struct
1048 {
1049 const char *Match;
1050 bool (*Handler)(CommandLine &);
1051 } Map[] = {{"update",&DoUpdate},
1052 {"upgrade",&DoUpgrade},
1053 {"install",&DoInstall},
303a1703 1054 {"remove",&DoInstall},
0a8e3465
AL
1055 {"dist-upgrade",&DoDistUpgrade},
1056 {"dselect-upgrade",&DoDSelectUpgrade},
1057 {"clean",&DoClean},
1058 {"check",&DoCheck},
1059 {0,0}};
1060 int I;
1061 for (I = 0; Map[I].Match != 0; I++)
1062 {
1063 if (strcmp(CmdL.FileList[0],Map[I].Match) == 0)
1064 {
0919e3f9
AL
1065 if (Map[I].Handler(CmdL) == false && _error->PendingError() == false)
1066 _error->Error("Handler silently failed");
0a8e3465
AL
1067 break;
1068 }
1069 }
1070
1071 // No matching name
1072 if (Map[I].Match == 0)
1073 _error->Error("Invalid operation %s", CmdL.FileList[0]);
1074
1075 // Print any errors or warnings found during parsing
1076 if (_error->empty() == false)
1077 {
1078 bool Errors = _error->PendingError();
1079 _error->DumpErrors();
1080 if (Errors == true)
1081 cout << "Returning 100." << endl;
1082 return Errors == true?100:0;
1083 }
1084
1085 return 0;
1086}