Made autoclean respect 'q' settings. Closes: #63023
[ntk/apt.git] / cmdline / apt-get.cc
1 // -*- mode: cpp; mode: fold -*-
2 // Description /*{{{*/
3 // $Id: apt-get.cc,v 1.97 2000/05/12 05:11:54 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/statvfs.h>
51 #include <signal.h>
52 #include <unistd.h>
53 #include <stdio.h>
54 #include <errno.h>
55 #include <regex.h>
56 #include <sys/wait.h>
57 /*}}}*/
58
59 ostream c0out;
60 ostream c1out;
61 ostream c2out;
62 ofstream devnull("/dev/null");
63 unsigned int ScreenWidth = 80;
64
65 // class CacheFile - Cover class for some dependency cache functions /*{{{*/
66 // ---------------------------------------------------------------------
67 /* */
68 class CacheFile : public pkgCacheFile
69 {
70 static pkgCache *SortCache;
71 static int NameComp(const void *a,const void *b);
72
73 public:
74 pkgCache::Package **List;
75
76 void Sort();
77 bool CheckDeps(bool AllowBroken = false);
78 bool Open(bool WithLock = true)
79 {
80 OpTextProgress Prog(*_config);
81 if (pkgCacheFile::Open(Prog,WithLock) == false)
82 return false;
83 Sort();
84 return true;
85 };
86 CacheFile() : List(0) {};
87 };
88 /*}}}*/
89
90 // YnPrompt - Yes No Prompt. /*{{{*/
91 // ---------------------------------------------------------------------
92 /* Returns true on a Yes.*/
93 bool YnPrompt()
94 {
95 if (_config->FindB("APT::Get::Assume-Yes",false) == true)
96 {
97 c1out << 'Y' << endl;
98 return true;
99 }
100
101 char C = 0;
102 char Jnk = 0;
103 read(STDIN_FILENO,&C,1);
104 while (C != '\n' && Jnk != '\n') read(STDIN_FILENO,&Jnk,1);
105
106 if (!(C == 'Y' || C == 'y' || C == '\n' || C == '\r'))
107 return false;
108 return true;
109 }
110 /*}}}*/
111 // AnalPrompt - Annoying Yes No Prompt. /*{{{*/
112 // ---------------------------------------------------------------------
113 /* Returns true on a Yes.*/
114 bool AnalPrompt(const char *Text)
115 {
116 char Buf[1024];
117 cin.getline(Buf,sizeof(Buf));
118 if (strcmp(Buf,Text) == 0)
119 return true;
120 return false;
121 }
122 /*}}}*/
123 // ShowList - Show a list /*{{{*/
124 // ---------------------------------------------------------------------
125 /* This prints out a string of space seperated words with a title and
126 a two space indent line wraped to the current screen width. */
127 bool ShowList(ostream &out,string Title,string List)
128 {
129 if (List.empty() == true)
130 return true;
131
132 // Acount for the leading space
133 int ScreenWidth = ::ScreenWidth - 3;
134
135 out << Title << endl;
136 string::size_type Start = 0;
137 while (Start < List.size())
138 {
139 string::size_type End;
140 if (Start + ScreenWidth >= List.size())
141 End = List.size();
142 else
143 End = List.rfind(' ',Start+ScreenWidth);
144
145 if (End == string::npos || End < Start)
146 End = Start + ScreenWidth;
147 out << " " << string(List,Start,End - Start) << endl;
148 Start = End + 1;
149 }
150 return false;
151 }
152 /*}}}*/
153 // ShowBroken - Debugging aide /*{{{*/
154 // ---------------------------------------------------------------------
155 /* This prints out the names of all the packages that are broken along
156 with the name of each each broken dependency and a quite version
157 description. */
158 void ShowBroken(ostream &out,CacheFile &Cache,bool Now)
159 {
160 out << "Sorry, but the following packages have unmet dependencies:" << endl;
161 for (unsigned J = 0; J < Cache->Head().PackageCount; J++)
162 {
163 pkgCache::PkgIterator I(Cache,Cache.List[J]);
164
165 if (Cache[I].InstBroken() == false)
166 continue;
167
168 // Print out each package and the failed dependencies
169 out <<" " << I.Name() << ":";
170 unsigned Indent = strlen(I.Name()) + 3;
171 bool First = true;
172 if (Cache[I].InstVerIter(Cache).end() == true)
173 {
174 cout << endl;
175 continue;
176 }
177
178 for (pkgCache::DepIterator D = Cache[I].InstVerIter(Cache).DependsList(); D.end() == false;)
179 {
180 // Compute a single dependency element (glob or)
181 pkgCache::DepIterator Start;
182 pkgCache::DepIterator End;
183 D.GlobOr(Start,End);
184
185 if (Cache->IsImportantDep(End) == false ||
186 (Cache[End] & pkgDepCache::DepGInstall) == pkgDepCache::DepGInstall)
187 continue;
188
189 bool FirstOr = true;
190 while (1)
191 {
192 if (First == false)
193 for (unsigned J = 0; J != Indent; J++)
194 out << ' ';
195 First = false;
196
197 if (FirstOr == false)
198 {
199 for (unsigned J = 0; J != strlen(End.DepType()) + 3; J++)
200 out << ' ';
201 }
202 else
203 out << ' ' << End.DepType() << ": ";
204 FirstOr = false;
205
206 out << Start.TargetPkg().Name();
207
208 // Show a quick summary of the version requirements
209 if (Start.TargetVer() != 0)
210 out << " (" << Start.CompType() << " " << Start.TargetVer() <<
211 ")";
212
213 /* Show a summary of the target package if possible. In the case
214 of virtual packages we show nothing */
215 pkgCache::PkgIterator Targ = Start.TargetPkg();
216 if (Targ->ProvidesList == 0)
217 {
218 out << " but ";
219 pkgCache::VerIterator Ver = Cache[Targ].InstVerIter(Cache);
220 if (Ver.end() == false)
221 out << Ver.VerStr() << (Now?" is installed":" is to be installed");
222 else
223 {
224 if (Cache[Targ].CandidateVerIter(Cache).end() == true)
225 {
226 if (Targ->ProvidesList == 0)
227 out << "it is not installable";
228 else
229 out << "it is a virtual package";
230 }
231 else
232 out << (Now?"it is not installed":"it is not going to be installed");
233 }
234 }
235
236 if (Start != End)
237 cout << " or";
238 out << endl;
239
240 if (Start == End)
241 break;
242 Start++;
243 }
244 }
245 }
246 }
247 /*}}}*/
248 // ShowNew - Show packages to newly install /*{{{*/
249 // ---------------------------------------------------------------------
250 /* */
251 void ShowNew(ostream &out,CacheFile &Cache)
252 {
253 /* Print out a list of packages that are going to be removed extra
254 to what the user asked */
255 string List;
256 for (unsigned J = 0; J < Cache->Head().PackageCount; J++)
257 {
258 pkgCache::PkgIterator I(Cache,Cache.List[J]);
259 if (Cache[I].NewInstall() == true)
260 List += string(I.Name()) + " ";
261 }
262
263 ShowList(out,"The following NEW packages will be installed:",List);
264 }
265 /*}}}*/
266 // ShowDel - Show packages to delete /*{{{*/
267 // ---------------------------------------------------------------------
268 /* */
269 void ShowDel(ostream &out,CacheFile &Cache)
270 {
271 /* Print out a list of packages that are going to be removed extra
272 to what the user asked */
273 string List;
274 for (unsigned J = 0; J < Cache->Head().PackageCount; J++)
275 {
276 pkgCache::PkgIterator I(Cache,Cache.List[J]);
277 if (Cache[I].Delete() == true)
278 {
279 if ((Cache[I].iFlags & pkgDepCache::Purge) == pkgDepCache::Purge)
280 List += string(I.Name()) + "* ";
281 else
282 List += string(I.Name()) + " ";
283 }
284 }
285
286 ShowList(out,"The following packages will be REMOVED:",List);
287 }
288 /*}}}*/
289 // ShowKept - Show kept packages /*{{{*/
290 // ---------------------------------------------------------------------
291 /* */
292 void ShowKept(ostream &out,CacheFile &Cache)
293 {
294 string List;
295 for (unsigned J = 0; J < Cache->Head().PackageCount; J++)
296 {
297 pkgCache::PkgIterator I(Cache,Cache.List[J]);
298
299 // Not interesting
300 if (Cache[I].Upgrade() == true || Cache[I].Upgradable() == false ||
301 I->CurrentVer == 0 || Cache[I].Delete() == true)
302 continue;
303
304 List += string(I.Name()) + " ";
305 }
306 ShowList(out,"The following packages have been kept back",List);
307 }
308 /*}}}*/
309 // ShowUpgraded - Show upgraded packages /*{{{*/
310 // ---------------------------------------------------------------------
311 /* */
312 void ShowUpgraded(ostream &out,CacheFile &Cache)
313 {
314 string List;
315 for (unsigned J = 0; J < Cache->Head().PackageCount; J++)
316 {
317 pkgCache::PkgIterator I(Cache,Cache.List[J]);
318
319 // Not interesting
320 if (Cache[I].Upgrade() == false || Cache[I].NewInstall() == true)
321 continue;
322
323 List += string(I.Name()) + " ";
324 }
325 ShowList(out,"The following packages will be upgraded",List);
326 }
327 /*}}}*/
328 // ShowHold - Show held but changed packages /*{{{*/
329 // ---------------------------------------------------------------------
330 /* */
331 bool ShowHold(ostream &out,CacheFile &Cache)
332 {
333 string List;
334 for (unsigned J = 0; J < Cache->Head().PackageCount; J++)
335 {
336 pkgCache::PkgIterator I(Cache,Cache.List[J]);
337 if (Cache[I].InstallVer != (pkgCache::Version *)I.CurrentVer() &&
338 I->SelectedState == pkgCache::State::Hold)
339 List += string(I.Name()) + " ";
340 }
341
342 return ShowList(out,"The following held packages will be changed:",List);
343 }
344 /*}}}*/
345 // ShowEssential - Show an essential package warning /*{{{*/
346 // ---------------------------------------------------------------------
347 /* This prints out a warning message that is not to be ignored. It shows
348 all essential packages and their dependents that are to be removed.
349 It is insanely risky to remove the dependents of an essential package! */
350 bool ShowEssential(ostream &out,CacheFile &Cache)
351 {
352 string List;
353 bool *Added = new bool[Cache->HeaderP->PackageCount];
354 for (unsigned int I = 0; I != Cache->HeaderP->PackageCount; I++)
355 Added[I] = false;
356
357 for (unsigned J = 0; J < Cache->Head().PackageCount; J++)
358 {
359 pkgCache::PkgIterator I(Cache,Cache.List[J]);
360 if ((I->Flags & pkgCache::Flag::Essential) != pkgCache::Flag::Essential)
361 continue;
362
363 // The essential package is being removed
364 if (Cache[I].Delete() == true)
365 {
366 if (Added[I->ID] == false)
367 {
368 Added[I->ID] = true;
369 List += string(I.Name()) + " ";
370 }
371 }
372
373 if (I->CurrentVer == 0)
374 continue;
375
376 // Print out any essential package depenendents that are to be removed
377 for (pkgDepCache::DepIterator D = I.CurrentVer().DependsList(); D.end() == false; D++)
378 {
379 // Skip everything but depends
380 if (D->Type != pkgCache::Dep::PreDepends &&
381 D->Type != pkgCache::Dep::Depends)
382 continue;
383
384 pkgCache::PkgIterator P = D.SmartTargetPkg();
385 if (Cache[P].Delete() == true)
386 {
387 if (Added[P->ID] == true)
388 continue;
389 Added[P->ID] = true;
390
391 char S[300];
392 sprintf(S,"%s (due to %s) ",P.Name(),I.Name());
393 List += S;
394 }
395 }
396 }
397
398 delete [] Added;
399 if (List.empty() == false)
400 out << "WARNING: The following essential packages will be removed" << endl;
401 return ShowList(out,"This should NOT be done unless you know exactly what you are doing!",List);
402 }
403 /*}}}*/
404 // Stats - Show some statistics /*{{{*/
405 // ---------------------------------------------------------------------
406 /* */
407 void Stats(ostream &out,pkgDepCache &Dep)
408 {
409 unsigned long Upgrade = 0;
410 unsigned long Install = 0;
411 unsigned long ReInstall = 0;
412 for (pkgCache::PkgIterator I = Dep.PkgBegin(); I.end() == false; I++)
413 {
414 if (Dep[I].NewInstall() == true)
415 Install++;
416 else
417 if (Dep[I].Upgrade() == true)
418 Upgrade++;
419 if (Dep[I].Delete() == false && (Dep[I].iFlags & pkgDepCache::ReInstall) == pkgDepCache::ReInstall)
420 ReInstall++;
421 }
422
423 out << Upgrade << " packages upgraded, " <<
424 Install << " newly installed, ";
425 if (ReInstall != 0)
426 out << ReInstall << " reinstalled, ";
427 out << Dep.DelCount() << " to remove and " <<
428 Dep.KeepCount() << " not upgraded." << endl;
429
430 if (Dep.BadCount() != 0)
431 out << Dep.BadCount() << " packages not fully installed or removed." << endl;
432 }
433 /*}}}*/
434
435 // CacheFile::NameComp - QSort compare by name /*{{{*/
436 // ---------------------------------------------------------------------
437 /* */
438 pkgCache *CacheFile::SortCache = 0;
439 int CacheFile::NameComp(const void *a,const void *b)
440 {
441 if (*(pkgCache::Package **)a == 0 || *(pkgCache::Package **)b == 0)
442 return *(pkgCache::Package **)a - *(pkgCache::Package **)b;
443
444 const pkgCache::Package &A = **(pkgCache::Package **)a;
445 const pkgCache::Package &B = **(pkgCache::Package **)b;
446
447 return strcmp(SortCache->StrP + A.Name,SortCache->StrP + B.Name);
448 }
449 /*}}}*/
450 // CacheFile::Sort - Sort by name /*{{{*/
451 // ---------------------------------------------------------------------
452 /* */
453 void CacheFile::Sort()
454 {
455 delete [] List;
456 List = new pkgCache::Package *[Cache->Head().PackageCount];
457 memset(List,0,sizeof(*List)*Cache->Head().PackageCount);
458 pkgCache::PkgIterator I = Cache->PkgBegin();
459 for (;I.end() != true; I++)
460 List[I->ID] = I;
461
462 SortCache = *this;
463 qsort(List,Cache->Head().PackageCount,sizeof(*List),NameComp);
464 }
465 /*}}}*/
466 // CacheFile::Open - Open the cache file /*{{{*/
467 // ---------------------------------------------------------------------
468 /* This routine generates the caches and then opens the dependency cache
469 and verifies that the system is OK. */
470 bool CacheFile::CheckDeps(bool AllowBroken)
471 {
472 if (_error->PendingError() == true)
473 return false;
474
475 // Check that the system is OK
476 if (Cache->DelCount() != 0 || Cache->InstCount() != 0)
477 return _error->Error("Internal Error, non-zero counts");
478
479 // Apply corrections for half-installed packages
480 if (pkgApplyStatus(*Cache) == false)
481 return false;
482
483 // Nothing is broken
484 if (Cache->BrokenCount() == 0 || AllowBroken == true)
485 return true;
486
487 // Attempt to fix broken things
488 if (_config->FindB("APT::Get::Fix-Broken",false) == true)
489 {
490 c1out << "Correcting dependencies..." << flush;
491 if (pkgFixBroken(*Cache) == false || Cache->BrokenCount() != 0)
492 {
493 c1out << " failed." << endl;
494 ShowBroken(c1out,*this,true);
495
496 return _error->Error("Unable to correct dependencies");
497 }
498 if (pkgMinimizeUpgrade(*Cache) == false)
499 return _error->Error("Unable to minimize the upgrade set");
500
501 c1out << " Done" << endl;
502 }
503 else
504 {
505 c1out << "You might want to run `apt-get -f install' to correct these." << endl;
506 ShowBroken(c1out,*this,true);
507
508 return _error->Error("Unmet dependencies. Try using -f.");
509 }
510
511 return true;
512 }
513 /*}}}*/
514
515 // InstallPackages - Actually download and install the packages /*{{{*/
516 // ---------------------------------------------------------------------
517 /* This displays the informative messages describing what is going to
518 happen and then calls the download routines */
519 bool InstallPackages(CacheFile &Cache,bool ShwKept,bool Ask = true,
520 bool Saftey = true)
521 {
522 if (_config->FindB("APT::Get::Purge",false) == true)
523 {
524 pkgCache::PkgIterator I = Cache->PkgBegin();
525 for (; I.end() == false; I++)
526 {
527 if (I.Purge() == false && Cache[I].Mode == pkgDepCache::ModeDelete)
528 Cache->MarkDelete(I,true);
529 }
530 }
531
532 bool Fail = false;
533 bool Essential = false;
534
535 // Show all the various warning indicators
536 ShowDel(c1out,Cache);
537 ShowNew(c1out,Cache);
538 if (ShwKept == true)
539 ShowKept(c1out,Cache);
540 Fail |= !ShowHold(c1out,Cache);
541 if (_config->FindB("APT::Get::Show-Upgraded",false) == true)
542 ShowUpgraded(c1out,Cache);
543 Essential = !ShowEssential(c1out,Cache);
544 Fail |= Essential;
545 Stats(c1out,Cache);
546
547 // Sanity check
548 if (Cache->BrokenCount() != 0)
549 {
550 ShowBroken(c1out,Cache,false);
551 return _error->Error("Internal Error, InstallPackages was called with broken packages!");
552 }
553
554 if (Cache->DelCount() == 0 && Cache->InstCount() == 0 &&
555 Cache->BadCount() == 0)
556 return true;
557
558 // No remove flag
559 if (Cache->DelCount() != 0 && _config->FindB("APT::Get::No-Remove",false) == true)
560 return _error->Error("Packages need to be removed but No Remove was specified.");
561
562 // Run the simulator ..
563 if (_config->FindB("APT::Get::Simulate") == true)
564 {
565 pkgSimulate PM(Cache);
566 pkgPackageManager::OrderResult Res = PM.DoInstall();
567 if (Res == pkgPackageManager::Failed)
568 return false;
569 if (Res != pkgPackageManager::Completed)
570 return _error->Error("Internal Error, Ordering didn't finish");
571 return true;
572 }
573
574 // Create the text record parser
575 pkgRecords Recs(Cache);
576 if (_error->PendingError() == true)
577 return false;
578
579 // Lock the archive directory
580 FileFd Lock;
581 if (_config->FindB("Debug::NoLocking",false) == false)
582 {
583 Lock.Fd(GetLock(_config->FindDir("Dir::Cache::Archives") + "lock"));
584 if (_error->PendingError() == true)
585 return _error->Error("Unable to lock the download directory");
586 }
587
588 // Create the download object
589 AcqTextStatus Stat(ScreenWidth,_config->FindI("quiet",0));
590 pkgAcquire Fetcher(&Stat);
591
592 // Read the source list
593 pkgSourceList List;
594 if (List.ReadMainList() == false)
595 return _error->Error("The list of sources could not be read.");
596
597 // Create the package manager and prepare to download
598 pkgDPkgPM PM(Cache);
599 if (PM.GetArchives(&Fetcher,&List,&Recs) == false ||
600 _error->PendingError() == true)
601 return false;
602
603 // Display statistics
604 unsigned long FetchBytes = Fetcher.FetchNeeded();
605 unsigned long FetchPBytes = Fetcher.PartialPresent();
606 unsigned long DebBytes = Fetcher.TotalNeeded();
607 if (DebBytes != Cache->DebSize())
608 {
609 c0out << DebBytes << ',' << Cache->DebSize() << endl;
610 c0out << "How odd.. The sizes didn't match, email apt@packages.debian.org" << endl;
611 }
612
613 // Number of bytes
614 c1out << "Need to get ";
615 if (DebBytes != FetchBytes)
616 c1out << SizeToStr(FetchBytes) << "B/" << SizeToStr(DebBytes) << 'B';
617 else
618 c1out << SizeToStr(DebBytes) << 'B';
619
620 c1out << " of archives. After unpacking ";
621
622 // Size delta
623 if (Cache->UsrSize() >= 0)
624 c1out << SizeToStr(Cache->UsrSize()) << "B will be used." << endl;
625 else
626 c1out << SizeToStr(-1*Cache->UsrSize()) << "B will be freed." << endl;
627
628 if (_error->PendingError() == true)
629 return false;
630
631 /* Check for enough free space, but only if we are actually going to
632 download */
633 if (_config->FindB("APT::Get::Print-URIs") == false)
634 {
635 struct statvfs Buf;
636 string OutputDir = _config->FindDir("Dir::Cache::Archives");
637 if (statvfs(OutputDir.c_str(),&Buf) != 0)
638 return _error->Errno("statvfs","Couldn't determine free space in %s",
639 OutputDir.c_str());
640 if (unsigned(Buf.f_bfree) < (FetchBytes - FetchPBytes)/Buf.f_bsize)
641 return _error->Error("Sorry, you don't have enough free space in %s to hold all the .debs.",
642 OutputDir.c_str());
643 }
644
645 // Fail safe check
646 if (_config->FindI("quiet",0) >= 2 ||
647 _config->FindB("APT::Get::Assume-Yes",false) == true)
648 {
649 if (Fail == true && _config->FindB("APT::Get::Force-Yes",false) == false)
650 return _error->Error("There are problems and -y was used without --force-yes");
651 }
652
653 if (Essential == true && Saftey == true)
654 {
655 if (_config->FindB("APT::Get::Trivial-Only",false) == true)
656 return _error->Error("Trivial Only specified but this is not a trivial operation.");
657
658 c2out << "You are about to do something potentially harmful" << endl;
659 c2out << "To continue type in the phrase 'Yes, I understand this may be bad'" << endl;
660 c2out << " ?] " << flush;
661 if (AnalPrompt("Yes, I understand this may be bad") == false)
662 {
663 c2out << "Abort." << endl;
664 exit(1);
665 }
666 }
667 else
668 {
669 // Prompt to continue
670 if (Ask == true || Fail == true)
671 {
672 if (_config->FindB("APT::Get::Trivial-Only",false) == true)
673 return _error->Error("Trivial Only specified but this is not a trivial operation.");
674
675 if (_config->FindI("quiet",0) < 2 &&
676 _config->FindB("APT::Get::Assume-Yes",false) == false)
677 {
678 c2out << "Do you want to continue? [Y/n] " << flush;
679
680 if (YnPrompt() == false)
681 {
682 c2out << "Abort." << endl;
683 exit(1);
684 }
685 }
686 }
687 }
688
689 // Just print out the uris an exit if the --print-uris flag was used
690 if (_config->FindB("APT::Get::Print-URIs") == true)
691 {
692 pkgAcquire::UriIterator I = Fetcher.UriBegin();
693 for (; I != Fetcher.UriEnd(); I++)
694 cout << '\'' << I->URI << "' " << flNotDir(I->Owner->DestFile) << ' ' <<
695 I->Owner->FileSize << ' ' << I->Owner->MD5Sum() << endl;
696 return true;
697 }
698
699 // Run it
700 while (1)
701 {
702 bool Transient = false;
703 if (_config->FindB("APT::Get::No-Download",false) == true)
704 {
705 for (pkgAcquire::Item **I = Fetcher.ItemsBegin(); I < Fetcher.ItemsEnd();)
706 {
707 if ((*I)->Local == true)
708 {
709 I++;
710 continue;
711 }
712
713 // Close the item and check if it was found in cache
714 (*I)->Finished();
715 if ((*I)->Complete == false)
716 Transient = true;
717
718 // Clear it out of the fetch list
719 delete *I;
720 I = Fetcher.ItemsBegin();
721 }
722 }
723
724 if (Fetcher.Run() == pkgAcquire::Failed)
725 return false;
726
727 // Print out errors
728 bool Failed = false;
729 for (pkgAcquire::Item **I = Fetcher.ItemsBegin(); I != Fetcher.ItemsEnd(); I++)
730 {
731 if ((*I)->Status == pkgAcquire::Item::StatDone &&
732 (*I)->Complete == true)
733 continue;
734
735 if ((*I)->Status == pkgAcquire::Item::StatIdle)
736 {
737 Transient = true;
738 // Failed = true;
739 continue;
740 }
741
742 cerr << "Failed to fetch " << (*I)->DescURI() << endl;
743 cerr << " " << (*I)->ErrorText << endl;
744 Failed = true;
745 }
746
747 /* If we are in no download mode and missing files and there were
748 'failures' then the user must specify -m. Furthermore, there
749 is no such thing as a transient error in no-download mode! */
750 if (Transient == true &&
751 _config->FindB("APT::Get::No-Download",false) == true)
752 {
753 Transient = false;
754 Failed = true;
755 }
756
757 if (_config->FindB("APT::Get::Download-Only",false) == true)
758 {
759 if (Failed == true && _config->FindB("APT::Get::Fix-Missing",false) == false)
760 return _error->Error("Some files failed to download");
761 return true;
762 }
763
764 if (Failed == true && _config->FindB("APT::Get::Fix-Missing",false) == false)
765 {
766 return _error->Error("Unable to fetch some archives, maybe try with --fix-missing?");
767 }
768
769 if (Transient == true && Failed == true)
770 return _error->Error("--fix-missing and media swapping is not currently supported");
771
772 // Try to deal with missing package files
773 if (Failed == true && PM.FixMissing() == false)
774 {
775 cerr << "Unable to correct missing packages." << endl;
776 return _error->Error("Aborting Install.");
777 }
778
779 Cache.ReleaseLock();
780 pkgPackageManager::OrderResult Res = PM.DoInstall();
781 if (Res == pkgPackageManager::Failed || _error->PendingError() == true)
782 return false;
783 if (Res == pkgPackageManager::Completed)
784 return true;
785
786 // Reload the fetcher object and loop again for media swapping
787 Fetcher.Shutdown();
788 if (PM.GetArchives(&Fetcher,&List,&Recs) == false)
789 return false;
790 }
791 }
792 /*}}}*/
793 // TryToInstall - Try to install a single package /*{{{*/
794 // ---------------------------------------------------------------------
795 /* This used to be inlined in DoInstall, but with the advent of regex package
796 name matching it was split out.. */
797 bool TryToInstall(pkgCache::PkgIterator Pkg,pkgDepCache &Cache,
798 pkgProblemResolver &Fix,bool Remove,bool BrokenFix,
799 unsigned int &ExpectedInst,bool AllowFail = true)
800 {
801 /* This is a pure virtual package and there is a single available
802 provides */
803 if (Cache[Pkg].CandidateVer == 0 && Pkg->ProvidesList != 0 &&
804 Pkg.ProvidesList()->NextProvides == 0)
805 {
806 pkgCache::PkgIterator Tmp = Pkg.ProvidesList().OwnerPkg();
807 c1out << "Note, selecting " << Tmp.Name() << " instead of " << Pkg.Name() << endl;
808 Pkg = Tmp;
809 }
810
811 // Handle the no-upgrade case
812 if (_config->FindB("APT::Get::no-upgrade",false) == true &&
813 Pkg->CurrentVer != 0)
814 {
815 if (AllowFail == true)
816 c1out << "Skipping " << Pkg.Name() << ", it is already installed and no-upgrade is set." << endl;
817 return true;
818 }
819
820 // Check if there is something at all to install
821 pkgDepCache::StateCache &State = Cache[Pkg];
822 if (Remove == true && Pkg->CurrentVer == 0)
823 {
824 if (AllowFail == false)
825 return false;
826 return _error->Error("Package %s is not installed",Pkg.Name());
827 }
828
829 if (State.CandidateVer == 0 && Remove == false)
830 {
831 if (AllowFail == false)
832 return false;
833
834 if (Pkg->ProvidesList != 0)
835 {
836 c1out << "Package " << Pkg.Name() << " is a virtual package provided by:" << endl;
837
838 pkgCache::PrvIterator I = Pkg.ProvidesList();
839 for (; I.end() == false; I++)
840 {
841 pkgCache::PkgIterator Pkg = I.OwnerPkg();
842
843 if (Cache[Pkg].CandidateVerIter(Cache) == I.OwnerVer())
844 {
845 if (Cache[Pkg].Install() == true && Cache[Pkg].NewInstall() == false)
846 c1out << " " << Pkg.Name() << " " << I.OwnerVer().VerStr() <<
847 " [Installed]"<< endl;
848 else
849 c1out << " " << Pkg.Name() << " " << I.OwnerVer().VerStr() << endl;
850 }
851 }
852 c1out << "You should explicitly select one to install." << endl;
853 }
854 else
855 {
856 c1out << "Package " << Pkg.Name() << " has no available version, but exists in the database." << endl;
857 c1out << "This typically means that the package was mentioned in a dependency and " << endl;
858 c1out << "never uploaded, has been obsoleted or is not available with the contents " << endl;
859 c1out << "of sources.list" << endl;
860
861 string List;
862 pkgCache::DepIterator Dep = Pkg.RevDependsList();
863 for (; Dep.end() == false; Dep++)
864 {
865 if (Dep->Type != pkgCache::Dep::Replaces)
866 continue;
867 List += string(Dep.ParentPkg().Name()) + " ";
868 }
869 ShowList(c1out,"However the following packages replace it:",List);
870 }
871
872 _error->Error("Package %s has no installation candidate",Pkg.Name());
873 return false;
874 }
875
876 Fix.Clear(Pkg);
877 Fix.Protect(Pkg);
878 if (Remove == true)
879 {
880 Fix.Remove(Pkg);
881 Cache.MarkDelete(Pkg,_config->FindB("APT::Get::Purge",false));
882 return true;
883 }
884
885 // Install it
886 Cache.MarkInstall(Pkg,false);
887 if (State.Install() == false)
888 {
889 if (_config->FindB("APT::Get::ReInstall",false) == true)
890 {
891 if (Pkg->CurrentVer == 0 || Pkg.CurrentVer().Downloadable() == false)
892 c1out << "Sorry, re-installation of " << Pkg.Name() << " is not possible, it cannot be downloaded" << endl;
893 else
894 Cache.SetReInstall(Pkg,true);
895 }
896 else
897 {
898 if (AllowFail == true)
899 c1out << "Sorry, " << Pkg.Name() << " is already the newest version" << endl;
900 }
901 }
902 else
903 ExpectedInst++;
904
905 // Install it with autoinstalling enabled.
906 if (State.InstBroken() == true && BrokenFix == false)
907 Cache.MarkInstall(Pkg,true);
908 return true;
909 }
910 /*}}}*/
911
912 // DoUpdate - Update the package lists /*{{{*/
913 // ---------------------------------------------------------------------
914 /* */
915 bool DoUpdate(CommandLine &)
916 {
917 // Get the source list
918 pkgSourceList List;
919 if (List.ReadMainList() == false)
920 return false;
921
922 // Lock the list directory
923 FileFd Lock;
924 if (_config->FindB("Debug::NoLocking",false) == false)
925 {
926 Lock.Fd(GetLock(_config->FindDir("Dir::State::Lists") + "lock"));
927 if (_error->PendingError() == true)
928 return _error->Error("Unable to lock the list directory");
929 }
930
931 // Create the download object
932 AcqTextStatus Stat(ScreenWidth,_config->FindI("quiet",0));
933 pkgAcquire Fetcher(&Stat);
934
935 // Populate it with the source selection
936 pkgSourceList::const_iterator I;
937 for (I = List.begin(); I != List.end(); I++)
938 {
939 new pkgAcqIndex(&Fetcher,I);
940 if (_error->PendingError() == true)
941 return false;
942 }
943
944 // Run it
945 if (Fetcher.Run() == pkgAcquire::Failed)
946 return false;
947
948 bool Failed = false;
949 for (pkgAcquire::Item **I = Fetcher.ItemsBegin(); I != Fetcher.ItemsEnd(); I++)
950 {
951 if ((*I)->Status == pkgAcquire::Item::StatDone)
952 continue;
953
954 (*I)->Finished();
955
956 cerr << "Failed to fetch " << (*I)->DescURI() << endl;
957 cerr << " " << (*I)->ErrorText << endl;
958 Failed = true;
959 }
960
961 // Clean out any old list files
962 if (_config->FindB("APT::Get::List-Cleanup",true) == true)
963 {
964 if (Fetcher.Clean(_config->FindDir("Dir::State::lists")) == false ||
965 Fetcher.Clean(_config->FindDir("Dir::State::lists") + "partial/") == false)
966 return false;
967 }
968
969 // Prepare the cache.
970 CacheFile Cache;
971 if (Cache.Open() == false)
972 return false;
973
974 if (Failed == true)
975 return _error->Error("Some index files failed to download, they have been ignored, or old ones used instead.");
976 return true;
977 }
978 /*}}}*/
979 // DoUpgrade - Upgrade all packages /*{{{*/
980 // ---------------------------------------------------------------------
981 /* Upgrade all packages without installing new packages or erasing old
982 packages */
983 bool DoUpgrade(CommandLine &CmdL)
984 {
985 CacheFile Cache;
986 if (Cache.Open() == false || Cache.CheckDeps() == false)
987 return false;
988
989 // Do the upgrade
990 if (pkgAllUpgrade(Cache) == false)
991 {
992 ShowBroken(c1out,Cache,false);
993 return _error->Error("Internal Error, AllUpgrade broke stuff");
994 }
995
996 return InstallPackages(Cache,true);
997 }
998 /*}}}*/
999 // DoInstall - Install packages from the command line /*{{{*/
1000 // ---------------------------------------------------------------------
1001 /* Install named packages */
1002 bool DoInstall(CommandLine &CmdL)
1003 {
1004 CacheFile Cache;
1005 if (Cache.Open() == false || Cache.CheckDeps(CmdL.FileSize() != 1) == false)
1006 return false;
1007
1008 // Enter the special broken fixing mode if the user specified arguments
1009 bool BrokenFix = false;
1010 if (Cache->BrokenCount() != 0)
1011 BrokenFix = true;
1012
1013 unsigned int ExpectedInst = 0;
1014 unsigned int Packages = 0;
1015 pkgProblemResolver Fix(Cache);
1016
1017 bool DefRemove = false;
1018 if (strcasecmp(CmdL.FileList[0],"remove") == 0)
1019 DefRemove = true;
1020
1021 for (const char **I = CmdL.FileList + 1; *I != 0; I++)
1022 {
1023 // Duplicate the string
1024 unsigned int Length = strlen(*I);
1025 char S[300];
1026 if (Length >= sizeof(S))
1027 continue;
1028 strcpy(S,*I);
1029
1030 // See if we are removing the package
1031 bool Remove = DefRemove;
1032 while (Cache->FindPkg(S).end() == true)
1033 {
1034 // Handle an optional end tag indicating what to do
1035 if (S[Length - 1] == '-')
1036 {
1037 Remove = true;
1038 S[--Length] = 0;
1039 continue;
1040 }
1041
1042 if (S[Length - 1] == '+')
1043 {
1044 Remove = false;
1045 S[--Length] = 0;
1046 continue;
1047 }
1048 break;
1049 }
1050
1051 // Locate the package
1052 pkgCache::PkgIterator Pkg = Cache->FindPkg(S);
1053 Packages++;
1054 if (Pkg.end() == true)
1055 {
1056 // Check if the name is a regex
1057 const char *I;
1058 for (I = S; *I != 0; I++)
1059 if (*I == '.' || *I == '?' || *I == '*')
1060 break;
1061 if (*I == 0)
1062 return _error->Error("Couldn't find package %s",S);
1063
1064 // Regexs must always be confirmed
1065 ExpectedInst += 1000;
1066
1067 // Compile the regex pattern
1068 regex_t Pattern;
1069 if (regcomp(&Pattern,S,REG_EXTENDED | REG_ICASE |
1070 REG_NOSUB) != 0)
1071 return _error->Error("Regex compilation error");
1072
1073 // Run over the matches
1074 bool Hit = false;
1075 for (Pkg = Cache->PkgBegin(); Pkg.end() == false; Pkg++)
1076 {
1077 if (regexec(&Pattern,Pkg.Name(),0,0,0) != 0)
1078 continue;
1079
1080 Hit |= TryToInstall(Pkg,Cache,Fix,Remove,BrokenFix,
1081 ExpectedInst,false);
1082 }
1083 regfree(&Pattern);
1084
1085 if (Hit == false)
1086 return _error->Error("Couldn't find package %s",S);
1087 }
1088 else
1089 {
1090 if (TryToInstall(Pkg,Cache,Fix,Remove,BrokenFix,ExpectedInst) == false)
1091 return false;
1092 }
1093 }
1094
1095 /* If we are in the Broken fixing mode we do not attempt to fix the
1096 problems. This is if the user invoked install without -f and gave
1097 packages */
1098 if (BrokenFix == true && Cache->BrokenCount() != 0)
1099 {
1100 c1out << "You might want to run `apt-get -f install' to correct these:" << endl;
1101 ShowBroken(c1out,Cache,false);
1102
1103 return _error->Error("Unmet dependencies. Try 'apt-get -f install' with no packages (or specify a solution).");
1104 }
1105
1106 // Call the scored problem resolver
1107 Fix.InstallProtect();
1108 if (Fix.Resolve(true) == false)
1109 _error->Discard();
1110
1111 // Now we check the state of the packages,
1112 if (Cache->BrokenCount() != 0)
1113 {
1114 c1out << "Some packages could not be installed. This may mean that you have" << endl;
1115 c1out << "requested an impossible situation or if you are using the unstable" << endl;
1116 c1out << "distribution that some required packages have not yet been created" << endl;
1117 c1out << "or been moved out of Incoming." << endl;
1118 if (Packages == 1)
1119 {
1120 c1out << endl;
1121 c1out << "Since you only requested a single operation it is extremely likely that" << endl;
1122 c1out << "the package is simply not installable and a bug report against" << endl;
1123 c1out << "that package should be filed." << endl;
1124 }
1125
1126 c1out << "The following information may help to resolve the situation:" << endl;
1127 c1out << endl;
1128 ShowBroken(c1out,Cache,false);
1129 return _error->Error("Sorry, broken packages");
1130 }
1131
1132 /* Print out a list of packages that are going to be installed extra
1133 to what the user asked */
1134 if (Cache->InstCount() != ExpectedInst)
1135 {
1136 string List;
1137 for (unsigned J = 0; J < Cache->Head().PackageCount; J++)
1138 {
1139 pkgCache::PkgIterator I(Cache,Cache.List[J]);
1140 if ((*Cache)[I].Install() == false)
1141 continue;
1142
1143 const char **J;
1144 for (J = CmdL.FileList + 1; *J != 0; J++)
1145 if (strcmp(*J,I.Name()) == 0)
1146 break;
1147
1148 if (*J == 0)
1149 List += string(I.Name()) + " ";
1150 }
1151
1152 ShowList(c1out,"The following extra packages will be installed:",List);
1153 }
1154
1155 // See if we need to prompt
1156 if (Cache->InstCount() == ExpectedInst && Cache->DelCount() == 0)
1157 return InstallPackages(Cache,false,false);
1158
1159 return InstallPackages(Cache,false);
1160 }
1161 /*}}}*/
1162 // DoDistUpgrade - Automatic smart upgrader /*{{{*/
1163 // ---------------------------------------------------------------------
1164 /* Intelligent upgrader that will install and remove packages at will */
1165 bool DoDistUpgrade(CommandLine &CmdL)
1166 {
1167 CacheFile Cache;
1168 if (Cache.Open() == false || Cache.CheckDeps() == false)
1169 return false;
1170
1171 c0out << "Calculating Upgrade... " << flush;
1172 if (pkgDistUpgrade(*Cache) == false)
1173 {
1174 c0out << "Failed" << endl;
1175 ShowBroken(c1out,Cache,false);
1176 return false;
1177 }
1178
1179 c0out << "Done" << endl;
1180
1181 return InstallPackages(Cache,true);
1182 }
1183 /*}}}*/
1184 // DoDSelectUpgrade - Do an upgrade by following dselects selections /*{{{*/
1185 // ---------------------------------------------------------------------
1186 /* Follows dselect's selections */
1187 bool DoDSelectUpgrade(CommandLine &CmdL)
1188 {
1189 CacheFile Cache;
1190 if (Cache.Open() == false || Cache.CheckDeps() == false)
1191 return false;
1192
1193 // Install everything with the install flag set
1194 pkgCache::PkgIterator I = Cache->PkgBegin();
1195 for (;I.end() != true; I++)
1196 {
1197 /* Install the package only if it is a new install, the autoupgrader
1198 will deal with the rest */
1199 if (I->SelectedState == pkgCache::State::Install)
1200 Cache->MarkInstall(I,false);
1201 }
1202
1203 /* Now install their deps too, if we do this above then order of
1204 the status file is significant for | groups */
1205 for (I = Cache->PkgBegin();I.end() != true; I++)
1206 {
1207 /* Install the package only if it is a new install, the autoupgrader
1208 will deal with the rest */
1209 if (I->SelectedState == pkgCache::State::Install)
1210 Cache->MarkInstall(I,true);
1211 }
1212
1213 // Apply erasures now, they override everything else.
1214 for (I = Cache->PkgBegin();I.end() != true; I++)
1215 {
1216 // Remove packages
1217 if (I->SelectedState == pkgCache::State::DeInstall ||
1218 I->SelectedState == pkgCache::State::Purge)
1219 Cache->MarkDelete(I,I->SelectedState == pkgCache::State::Purge);
1220 }
1221
1222 /* Resolve any problems that dselect created, allupgrade cannot handle
1223 such things. We do so quite agressively too.. */
1224 if (Cache->BrokenCount() != 0)
1225 {
1226 pkgProblemResolver Fix(Cache);
1227
1228 // Hold back held packages.
1229 if (_config->FindB("APT::Ingore-Hold",false) == false)
1230 {
1231 for (pkgCache::PkgIterator I = Cache->PkgBegin(); I.end() == false; I++)
1232 {
1233 if (I->SelectedState == pkgCache::State::Hold)
1234 {
1235 Fix.Protect(I);
1236 Cache->MarkKeep(I);
1237 }
1238 }
1239 }
1240
1241 if (Fix.Resolve() == false)
1242 {
1243 ShowBroken(c1out,Cache,false);
1244 return _error->Error("Internal Error, problem resolver broke stuff");
1245 }
1246 }
1247
1248 // Now upgrade everything
1249 if (pkgAllUpgrade(Cache) == false)
1250 {
1251 ShowBroken(c1out,Cache,false);
1252 return _error->Error("Internal Error, problem resolver broke stuff");
1253 }
1254
1255 return InstallPackages(Cache,false);
1256 }
1257 /*}}}*/
1258 // DoClean - Remove download archives /*{{{*/
1259 // ---------------------------------------------------------------------
1260 /* */
1261 bool DoClean(CommandLine &CmdL)
1262 {
1263 if (_config->FindB("APT::Get::Simulate") == true)
1264 {
1265 cout << "Del " << _config->FindDir("Dir::Cache::archives") << "* " <<
1266 _config->FindDir("Dir::Cache::archives") << "partial/*" << endl;
1267 return true;
1268 }
1269
1270 // Lock the archive directory
1271 FileFd Lock;
1272 if (_config->FindB("Debug::NoLocking",false) == false)
1273 {
1274 Lock.Fd(GetLock(_config->FindDir("Dir::Cache::Archives") + "lock"));
1275 if (_error->PendingError() == true)
1276 return _error->Error("Unable to lock the download directory");
1277 }
1278
1279 pkgAcquire Fetcher;
1280 Fetcher.Clean(_config->FindDir("Dir::Cache::archives"));
1281 Fetcher.Clean(_config->FindDir("Dir::Cache::archives") + "partial/");
1282 return true;
1283 }
1284 /*}}}*/
1285 // DoAutoClean - Smartly remove downloaded archives /*{{{*/
1286 // ---------------------------------------------------------------------
1287 /* This is similar to clean but it only purges things that cannot be
1288 downloaded, that is old versions of cached packages. */
1289 class LogCleaner : public pkgArchiveCleaner
1290 {
1291 protected:
1292 virtual void Erase(const char *File,string Pkg,string Ver,struct stat &St)
1293 {
1294 c1out << "Del " << Pkg << " " << Ver << " [" << SizeToStr(St.st_size) << "B]" << endl;
1295
1296 if (_config->FindB("APT::Get::Simulate") == false)
1297 unlink(File);
1298 };
1299 };
1300
1301 bool DoAutoClean(CommandLine &CmdL)
1302 {
1303 // Lock the archive directory
1304 FileFd Lock;
1305 if (_config->FindB("Debug::NoLocking",false) == false)
1306 {
1307 Lock.Fd(GetLock(_config->FindDir("Dir::Cache::Archives") + "lock"));
1308 if (_error->PendingError() == true)
1309 return _error->Error("Unable to lock the download directory");
1310 }
1311
1312 CacheFile Cache;
1313 if (Cache.Open() == false)
1314 return false;
1315
1316 LogCleaner Cleaner;
1317
1318 return Cleaner.Go(_config->FindDir("Dir::Cache::archives"),*Cache) &&
1319 Cleaner.Go(_config->FindDir("Dir::Cache::archives") + "partial/",*Cache);
1320 }
1321 /*}}}*/
1322 // DoCheck - Perform the check operation /*{{{*/
1323 // ---------------------------------------------------------------------
1324 /* Opening automatically checks the system, this command is mostly used
1325 for debugging */
1326 bool DoCheck(CommandLine &CmdL)
1327 {
1328 CacheFile Cache;
1329 Cache.Open();
1330 Cache.CheckDeps();
1331
1332 return true;
1333 }
1334 /*}}}*/
1335 // DoSource - Fetch a source archive /*{{{*/
1336 // ---------------------------------------------------------------------
1337 /* Fetch souce packages */
1338 struct DscFile
1339 {
1340 string Package;
1341 string Version;
1342 string Dsc;
1343 };
1344
1345 bool DoSource(CommandLine &CmdL)
1346 {
1347 CacheFile Cache;
1348 if (Cache.Open(false) == false)
1349 return false;
1350
1351 if (CmdL.FileSize() <= 1)
1352 return _error->Error("Must specify at least one package to fetch source for");
1353
1354 // Read the source list
1355 pkgSourceList List;
1356 if (List.ReadMainList() == false)
1357 return _error->Error("The list of sources could not be read.");
1358
1359 // Create the text record parsers
1360 pkgRecords Recs(Cache);
1361 pkgSrcRecords SrcRecs(List);
1362 if (_error->PendingError() == true)
1363 return false;
1364
1365 // Create the download object
1366 AcqTextStatus Stat(ScreenWidth,_config->FindI("quiet",0));
1367 pkgAcquire Fetcher(&Stat);
1368
1369 DscFile *Dsc = new DscFile[CmdL.FileSize()];
1370
1371 // Load the requestd sources into the fetcher
1372 unsigned J = 0;
1373 for (const char **I = CmdL.FileList + 1; *I != 0; I++, J++)
1374 {
1375 string Src;
1376
1377 /* Lookup the version of the package we would install if we were to
1378 install a version and determine the source package name, then look
1379 in the archive for a source package of the same name. In theory
1380 we could stash the version string as well and match that too but
1381 today there aren't multi source versions in the archive. */
1382 pkgCache::PkgIterator Pkg = Cache->FindPkg(*I);
1383 if (Pkg.end() == false)
1384 {
1385 pkgCache::VerIterator Ver = Cache->GetCandidateVer(Pkg);
1386 if (Ver.end() == false)
1387 {
1388 pkgRecords::Parser &Parse = Recs.Lookup(Ver.FileList());
1389 Src = Parse.SourcePkg();
1390 }
1391 }
1392
1393 // No source package name..
1394 if (Src.empty() == true)
1395 Src = *I;
1396
1397 // The best hit
1398 pkgSrcRecords::Parser *Last = 0;
1399 unsigned long Offset = 0;
1400 string Version;
1401 bool IsMatch = false;
1402
1403 // Iterate over all of the hits
1404 pkgSrcRecords::Parser *Parse;
1405 SrcRecs.Restart();
1406 while ((Parse = SrcRecs.Find(Src.c_str(),false)) != 0)
1407 {
1408 string Ver = Parse->Version();
1409
1410 // Skip name mismatches
1411 if (IsMatch == true && Parse->Package() != Src)
1412 continue;
1413
1414 // Newer version or an exact match
1415 if (Last == 0 || pkgVersionCompare(Version,Ver) < 0 ||
1416 (Parse->Package() == Src && IsMatch == false))
1417 {
1418 IsMatch = Parse->Package() == Src;
1419 Last = Parse;
1420 Offset = Parse->Offset();
1421 Version = Ver;
1422 }
1423 }
1424
1425 if (Last == 0)
1426 return _error->Error("Unable to find a source package for %s",Src.c_str());
1427
1428 // Back track
1429 vector<pkgSrcRecords::File> Lst;
1430 if (Last->Jump(Offset) == false || Last->Files(Lst) == false)
1431 return false;
1432
1433 // Load them into the fetcher
1434 for (vector<pkgSrcRecords::File>::const_iterator I = Lst.begin();
1435 I != Lst.end(); I++)
1436 {
1437 // Try to guess what sort of file it is we are getting.
1438 string Comp;
1439 if (I->Path.find(".dsc") != string::npos)
1440 {
1441 Comp = "dsc";
1442 Dsc[J].Package = Last->Package();
1443 Dsc[J].Version = Last->Version();
1444 Dsc[J].Dsc = flNotDir(I->Path);
1445 }
1446
1447 if (I->Path.find(".tar.gz") != string::npos)
1448 Comp = "tar";
1449 if (I->Path.find(".diff.gz") != string::npos)
1450 Comp = "diff";
1451
1452 // Diff only mode only fetches .diff files
1453 if (_config->FindB("APT::Get::Diff-Only",false) == true &&
1454 Comp != "diff")
1455 continue;
1456
1457 // Tar only mode only fetches .tar files
1458 if (_config->FindB("APT::Get::Tar-Only",false) == true &&
1459 Comp != "tar")
1460 continue;
1461
1462 new pkgAcqFile(&Fetcher,Last->Source()->ArchiveURI(I->Path),
1463 I->MD5Hash,I->Size,Last->Source()->SourceInfo(Src,
1464 Last->Version(),Comp),Src);
1465 }
1466 }
1467
1468 // Display statistics
1469 unsigned long FetchBytes = Fetcher.FetchNeeded();
1470 unsigned long FetchPBytes = Fetcher.PartialPresent();
1471 unsigned long DebBytes = Fetcher.TotalNeeded();
1472
1473 // Check for enough free space
1474 struct statvfs Buf;
1475 string OutputDir = ".";
1476 if (statvfs(OutputDir.c_str(),&Buf) != 0)
1477 return _error->Errno("statvfs","Couldn't determine free space in %s",
1478 OutputDir.c_str());
1479 if (unsigned(Buf.f_bfree) < (FetchBytes - FetchPBytes)/Buf.f_bsize)
1480 return _error->Error("Sorry, you don't have enough free space in %s",
1481 OutputDir.c_str());
1482
1483 // Number of bytes
1484 c1out << "Need to get ";
1485 if (DebBytes != FetchBytes)
1486 c1out << SizeToStr(FetchBytes) << "B/" << SizeToStr(DebBytes) << 'B';
1487 else
1488 c1out << SizeToStr(DebBytes) << 'B';
1489 c1out << " of source archives." << endl;
1490
1491 if (_config->FindB("APT::Get::Simulate",false) == true)
1492 {
1493 for (unsigned I = 0; I != J; I++)
1494 cout << "Fetch Source " << Dsc[I].Package << endl;
1495 return true;
1496 }
1497
1498 // Just print out the uris an exit if the --print-uris flag was used
1499 if (_config->FindB("APT::Get::Print-URIs") == true)
1500 {
1501 pkgAcquire::UriIterator I = Fetcher.UriBegin();
1502 for (; I != Fetcher.UriEnd(); I++)
1503 cout << '\'' << I->URI << "' " << flNotDir(I->Owner->DestFile) << ' ' <<
1504 I->Owner->FileSize << ' ' << I->Owner->MD5Sum() << endl;
1505 return true;
1506 }
1507
1508 // Run it
1509 if (Fetcher.Run() == pkgAcquire::Failed)
1510 return false;
1511
1512 // Print error messages
1513 bool Failed = false;
1514 for (pkgAcquire::Item **I = Fetcher.ItemsBegin(); I != Fetcher.ItemsEnd(); I++)
1515 {
1516 if ((*I)->Status == pkgAcquire::Item::StatDone &&
1517 (*I)->Complete == true)
1518 continue;
1519
1520 cerr << "Failed to fetch " << (*I)->DescURI() << endl;
1521 cerr << " " << (*I)->ErrorText << endl;
1522 Failed = true;
1523 }
1524 if (Failed == true)
1525 return _error->Error("Failed to fetch some archives.");
1526
1527 if (_config->FindB("APT::Get::Download-only",false) == true)
1528 return true;
1529
1530 // Unpack the sources
1531 pid_t Process = ExecFork();
1532
1533 if (Process == 0)
1534 {
1535 for (unsigned I = 0; I != J; I++)
1536 {
1537 string Dir = Dsc[I].Package + '-' + pkgBaseVersion(Dsc[I].Version.c_str());
1538
1539 // Diff only mode only fetches .diff files
1540 if (_config->FindB("APT::Get::Diff-Only",false) == true ||
1541 _config->FindB("APT::Get::Tar-Only",false) == true ||
1542 Dsc[I].Dsc.empty() == true)
1543 continue;
1544
1545 // See if the package is already unpacked
1546 struct stat Stat;
1547 if (stat(Dir.c_str(),&Stat) == 0 &&
1548 S_ISDIR(Stat.st_mode) != 0)
1549 {
1550 c0out << "Skipping unpack of already unpacked source in " << Dir << endl;
1551 }
1552 else
1553 {
1554 // Call dpkg-source
1555 char S[500];
1556 snprintf(S,sizeof(S),"%s -x %s",
1557 _config->Find("Dir::Bin::dpkg-source","dpkg-source").c_str(),
1558 Dsc[I].Dsc.c_str());
1559 if (system(S) != 0)
1560 {
1561 cerr << "Unpack command '" << S << "' failed." << endl;
1562 _exit(1);
1563 }
1564 }
1565
1566 // Try to compile it with dpkg-buildpackage
1567 if (_config->FindB("APT::Get::Compile",false) == true)
1568 {
1569 // Call dpkg-buildpackage
1570 char S[500];
1571 snprintf(S,sizeof(S),"cd %s && %s %s",
1572 Dir.c_str(),
1573 _config->Find("Dir::Bin::dpkg-buildpackage","dpkg-buildpackage").c_str(),
1574 _config->Find("DPkg::Build-Options","-b -uc").c_str());
1575
1576 if (system(S) != 0)
1577 {
1578 cerr << "Build command '" << S << "' failed." << endl;
1579 _exit(1);
1580 }
1581 }
1582 }
1583
1584 _exit(0);
1585 }
1586
1587 // Wait for the subprocess
1588 int Status = 0;
1589 while (waitpid(Process,&Status,0) != Process)
1590 {
1591 if (errno == EINTR)
1592 continue;
1593 return _error->Errno("waitpid","Couldn't wait for subprocess");
1594 }
1595
1596 if (WIFEXITED(Status) == 0 || WEXITSTATUS(Status) != 0)
1597 return _error->Error("Child process failed");
1598
1599 return true;
1600 }
1601 /*}}}*/
1602
1603 // ShowHelp - Show a help screen /*{{{*/
1604 // ---------------------------------------------------------------------
1605 /* */
1606 bool ShowHelp(CommandLine &CmdL)
1607 {
1608 cout << PACKAGE << ' ' << VERSION << " for " << ARCHITECTURE <<
1609 " compiled on " << __DATE__ << " " << __TIME__ << endl;
1610 if (_config->FindB("version") == true)
1611 return 100;
1612
1613 cout << "Usage: apt-get [options] command" << endl;
1614 cout << " apt-get [options] install pkg1 [pkg2 ...]" << endl;
1615 cout << endl;
1616 cout << "apt-get is a simple command line interface for downloading and" << endl;
1617 cout << "installing packages. The most frequently used commands are update" << endl;
1618 cout << "and install." << endl;
1619 cout << endl;
1620 cout << "Commands:" << endl;
1621 cout << " update - Retrieve new lists of packages" << endl;
1622 cout << " upgrade - Perform an upgrade" << endl;
1623 cout << " install - Install new packages (pkg is libc6 not libc6.deb)" << endl;
1624 cout << " remove - Remove packages" << endl;
1625 cout << " source - Download source archives" << endl;
1626 cout << " dist-upgrade - Distribution upgrade, see apt-get(8)" << endl;
1627 cout << " dselect-upgrade - Follow dselect selections" << endl;
1628 cout << " clean - Erase downloaded archive files" << endl;
1629 cout << " autoclean - Erase old downloaded archive files" << endl;
1630 cout << " check - Verify that there are no broken dependencies" << endl;
1631 cout << endl;
1632 cout << "Options:" << endl;
1633 cout << " -h This help text." << endl;
1634 cout << " -q Loggable output - no progress indicator" << endl;
1635 cout << " -qq No output except for errors" << endl;
1636 cout << " -d Download only - do NOT install or unpack archives" << endl;
1637 cout << " -s No-act. Perform ordering simulation" << endl;
1638 cout << " -y Assume Yes to all queries and do not prompt" << endl;
1639 cout << " -f Attempt to continue if the integrity check fails" << endl;
1640 cout << " -m Attempt to continue if archives are unlocatable" << endl;
1641 cout << " -u Show a list of upgraded packages as well" << endl;
1642 cout << " -b Build the source package after fetching it" << endl;
1643 cout << " -c=? Read this configuration file" << endl;
1644 cout << " -o=? Set an arbitary configuration option, eg -o dir::cache=/tmp" << endl;
1645 cout << "See the apt-get(8), sources.list(5) and apt.conf(5) manual" << endl;
1646 cout << "pages for more information and options." << endl;
1647 return 100;
1648 }
1649 /*}}}*/
1650 // GetInitialize - Initialize things for apt-get /*{{{*/
1651 // ---------------------------------------------------------------------
1652 /* */
1653 void GetInitialize()
1654 {
1655 _config->Set("quiet",0);
1656 _config->Set("help",false);
1657 _config->Set("APT::Get::Download-Only",false);
1658 _config->Set("APT::Get::Simulate",false);
1659 _config->Set("APT::Get::Assume-Yes",false);
1660 _config->Set("APT::Get::Fix-Broken",false);
1661 _config->Set("APT::Get::Force-Yes",false);
1662 _config->Set("APT::Get::APT::Get::No-List-Cleanup",true);
1663 }
1664 /*}}}*/
1665 // SigWinch - Window size change signal handler /*{{{*/
1666 // ---------------------------------------------------------------------
1667 /* */
1668 void SigWinch(int)
1669 {
1670 // Riped from GNU ls
1671 #ifdef TIOCGWINSZ
1672 struct winsize ws;
1673
1674 if (ioctl(1, TIOCGWINSZ, &ws) != -1 && ws.ws_col >= 5)
1675 ScreenWidth = ws.ws_col - 1;
1676 #endif
1677 }
1678 /*}}}*/
1679
1680 int main(int argc,const char *argv[])
1681 {
1682 CommandLine::Args Args[] = {
1683 {'h',"help","help",0},
1684 {'v',"version","version",0},
1685 {'q',"quiet","quiet",CommandLine::IntLevel},
1686 {'q',"silent","quiet",CommandLine::IntLevel},
1687 {'d',"download-only","APT::Get::Download-Only",0},
1688 {'b',"compile","APT::Get::Compile",0},
1689 {'b',"build","APT::Get::Compile",0},
1690 {'s',"simulate","APT::Get::Simulate",0},
1691 {'s',"just-print","APT::Get::Simulate",0},
1692 {'s',"recon","APT::Get::Simulate",0},
1693 {'s',"no-act","APT::Get::Simulate",0},
1694 {'y',"yes","APT::Get::Assume-Yes",0},
1695 {'y',"assume-yes","APT::Get::Assume-Yes",0},
1696 {'f',"fix-broken","APT::Get::Fix-Broken",0},
1697 {'u',"show-upgraded","APT::Get::Show-Upgraded",0},
1698 {'m',"ignore-missing","APT::Get::Fix-Missing",0},
1699 {0,"no-download","APT::Get::No-Download",0},
1700 {0,"fix-missing","APT::Get::Fix-Missing",0},
1701 {0,"ignore-hold","APT::Ingore-Hold",0},
1702 {0,"no-upgrade","APT::Get::no-upgrade",0},
1703 {0,"force-yes","APT::Get::force-yes",0},
1704 {0,"print-uris","APT::Get::Print-URIs",0},
1705 {0,"diff-only","APT::Get::Diff-Only",0},
1706 {0,"tar-only","APT::Get::tar-Only",0},
1707 {0,"purge","APT::Get::Purge",0},
1708 {0,"list-cleanup","APT::Get::List-Cleanup",0},
1709 {0,"reinstall","APT::Get::ReInstall",0},
1710 {0,"trivial-only","APT::Get::Trivial-Only",0},
1711 {0,"no-remove","APT::Get::No-Remove",0},
1712 {'c',"config-file",0,CommandLine::ConfigFile},
1713 {'o',"option",0,CommandLine::ArbItem},
1714 {0,0,0,0}};
1715 CommandLine::Dispatch Cmds[] = {{"update",&DoUpdate},
1716 {"upgrade",&DoUpgrade},
1717 {"install",&DoInstall},
1718 {"remove",&DoInstall},
1719 {"dist-upgrade",&DoDistUpgrade},
1720 {"dselect-upgrade",&DoDSelectUpgrade},
1721 {"clean",&DoClean},
1722 {"autoclean",&DoAutoClean},
1723 {"check",&DoCheck},
1724 {"source",&DoSource},
1725 {"help",&ShowHelp},
1726 {0,0}};
1727
1728 // Parse the command line and initialize the package library
1729 CommandLine CmdL(Args,_config);
1730 if (pkgInitialize(*_config) == false ||
1731 CmdL.Parse(argc,argv) == false)
1732 {
1733 _error->DumpErrors();
1734 return 100;
1735 }
1736
1737 // See if the help should be shown
1738 if (_config->FindB("help") == true ||
1739 _config->FindB("version") == true ||
1740 CmdL.FileSize() == 0)
1741 return ShowHelp(CmdL);
1742
1743 // Deal with stdout not being a tty
1744 if (ttyname(STDOUT_FILENO) == 0 && _config->FindI("quiet",0) < 1)
1745 _config->Set("quiet","1");
1746
1747 // Setup the output streams
1748 c0out.rdbuf(cout.rdbuf());
1749 c1out.rdbuf(cout.rdbuf());
1750 c2out.rdbuf(cout.rdbuf());
1751 if (_config->FindI("quiet",0) > 0)
1752 c0out.rdbuf(devnull.rdbuf());
1753 if (_config->FindI("quiet",0) > 1)
1754 c1out.rdbuf(devnull.rdbuf());
1755
1756 // Setup the signals
1757 signal(SIGPIPE,SIG_IGN);
1758 signal(SIGWINCH,SigWinch);
1759 SigWinch(0);
1760
1761 // Match the operation
1762 CmdL.DispatchArg(Cmds);
1763
1764 // Print any errors or warnings found during parsing
1765 if (_error->empty() == false)
1766 {
1767 bool Errors = _error->PendingError();
1768 _error->DumpErrors();
1769 return Errors == true?100:0;
1770 }
1771
1772 return 0;
1773 }