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