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