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