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