]> git.saurik.com Git - apt.git/blob - cmdline/apt-get.cc
5ead83ddf2e2e6a67dff76e1e7c55d4100879b51
[apt.git] / cmdline / apt-get.cc
1 // -*- mode: cpp; mode: fold -*-
2 // Description /*{{{*/
3 // $Id: apt-get.cc,v 1.156 2004/08/28 01:05:16 mdz 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 <config.h>
29
30 #include <apt-pkg/aptconfiguration.h>
31 #include <apt-pkg/error.h>
32 #include <apt-pkg/cmndline.h>
33 #include <apt-pkg/init.h>
34 #include <apt-pkg/depcache.h>
35 #include <apt-pkg/sourcelist.h>
36 #include <apt-pkg/algorithms.h>
37 #include <apt-pkg/acquire-item.h>
38 #include <apt-pkg/strutl.h>
39 #include <apt-pkg/fileutl.h>
40 #include <apt-pkg/clean.h>
41 #include <apt-pkg/srcrecords.h>
42 #include <apt-pkg/version.h>
43 #include <apt-pkg/cachefile.h>
44 #include <apt-pkg/cacheset.h>
45 #include <apt-pkg/sptr.h>
46 #include <apt-pkg/md5.h>
47 #include <apt-pkg/versionmatch.h>
48 #include <apt-pkg/progress.h>
49 #include <apt-pkg/pkgsystem.h>
50 #include <apt-pkg/pkgrecords.h>
51 #include <apt-pkg/indexfile.h>
52
53 #include "acqprogress.h"
54
55 #include <set>
56 #include <locale.h>
57 #include <langinfo.h>
58 #include <fstream>
59 #include <termios.h>
60 #include <sys/ioctl.h>
61 #include <sys/stat.h>
62 #include <sys/statfs.h>
63 #include <sys/statvfs.h>
64 #include <signal.h>
65 #include <unistd.h>
66 #include <stdio.h>
67 #include <errno.h>
68 #include <regex.h>
69 #include <sys/wait.h>
70 #include <sstream>
71
72 #include <apti18n.h>
73 /*}}}*/
74
75 #define RAMFS_MAGIC 0x858458f6
76
77 using namespace std;
78
79 ostream c0out(0);
80 ostream c1out(0);
81 ostream c2out(0);
82 ofstream devnull("/dev/null");
83 unsigned int ScreenWidth = 80 - 1; /* - 1 for the cursor */
84
85 // class CacheFile - Cover class for some dependency cache functions /*{{{*/
86 // ---------------------------------------------------------------------
87 /* */
88 class CacheFile : public pkgCacheFile
89 {
90 static pkgCache *SortCache;
91 static int NameComp(const void *a,const void *b);
92
93 public:
94 pkgCache::Package **List;
95
96 void Sort();
97 bool CheckDeps(bool AllowBroken = false);
98 bool BuildCaches(bool WithLock = true)
99 {
100 OpTextProgress Prog(*_config);
101 if (pkgCacheFile::BuildCaches(&Prog,WithLock) == false)
102 return false;
103 return true;
104 }
105 bool Open(bool WithLock = true)
106 {
107 OpTextProgress Prog(*_config);
108 if (pkgCacheFile::Open(&Prog,WithLock) == false)
109 return false;
110 Sort();
111
112 return true;
113 };
114 bool OpenForInstall()
115 {
116 if (_config->FindB("APT::Get::Print-URIs") == true)
117 return Open(false);
118 else
119 return Open(true);
120 }
121 CacheFile() : List(0) {};
122 ~CacheFile() {
123 delete[] List;
124 }
125 };
126 /*}}}*/
127
128 // YnPrompt - Yes No Prompt. /*{{{*/
129 // ---------------------------------------------------------------------
130 /* Returns true on a Yes.*/
131 bool YnPrompt(bool Default=true)
132 {
133 if (_config->FindB("APT::Get::Assume-Yes",false) == true)
134 {
135 c1out << _("Y") << endl;
136 return true;
137 }
138 else if (_config->FindB("APT::Get::Assume-No",false) == true)
139 {
140 c1out << _("N") << endl;
141 return false;
142 }
143
144 char response[1024] = "";
145 cin.getline(response, sizeof(response));
146
147 if (!cin)
148 return false;
149
150 if (strlen(response) == 0)
151 return Default;
152
153 regex_t Pattern;
154 int Res;
155
156 Res = regcomp(&Pattern, nl_langinfo(YESEXPR),
157 REG_EXTENDED|REG_ICASE|REG_NOSUB);
158
159 if (Res != 0) {
160 char Error[300];
161 regerror(Res,&Pattern,Error,sizeof(Error));
162 return _error->Error(_("Regex compilation error - %s"),Error);
163 }
164
165 Res = regexec(&Pattern, response, 0, NULL, 0);
166 if (Res == 0)
167 return true;
168 return false;
169 }
170 /*}}}*/
171 // AnalPrompt - Annoying Yes No Prompt. /*{{{*/
172 // ---------------------------------------------------------------------
173 /* Returns true on a Yes.*/
174 bool AnalPrompt(const char *Text)
175 {
176 char Buf[1024];
177 cin.getline(Buf,sizeof(Buf));
178 if (strcmp(Buf,Text) == 0)
179 return true;
180 return false;
181 }
182 /*}}}*/
183 // ShowList - Show a list /*{{{*/
184 // ---------------------------------------------------------------------
185 /* This prints out a string of space separated words with a title and
186 a two space indent line wraped to the current screen width. */
187 bool ShowList(ostream &out,string Title,string List,string VersionsList)
188 {
189 if (List.empty() == true)
190 return true;
191 // trim trailing space
192 int NonSpace = List.find_last_not_of(' ');
193 if (NonSpace != -1)
194 {
195 List = List.erase(NonSpace + 1);
196 if (List.empty() == true)
197 return true;
198 }
199
200 // Acount for the leading space
201 int ScreenWidth = ::ScreenWidth - 3;
202
203 out << Title << endl;
204 string::size_type Start = 0;
205 string::size_type VersionsStart = 0;
206 while (Start < List.size())
207 {
208 if(_config->FindB("APT::Get::Show-Versions",false) == true &&
209 VersionsList.size() > 0) {
210 string::size_type End;
211 string::size_type VersionsEnd;
212
213 End = List.find(' ',Start);
214 VersionsEnd = VersionsList.find('\n', VersionsStart);
215
216 out << " " << string(List,Start,End - Start) << " (" <<
217 string(VersionsList,VersionsStart,VersionsEnd - VersionsStart) <<
218 ")" << endl;
219
220 if (End == string::npos || End < Start)
221 End = Start + ScreenWidth;
222
223 Start = End + 1;
224 VersionsStart = VersionsEnd + 1;
225 } else {
226 string::size_type End;
227
228 if (Start + ScreenWidth >= List.size())
229 End = List.size();
230 else
231 End = List.rfind(' ',Start+ScreenWidth);
232
233 if (End == string::npos || End < Start)
234 End = Start + ScreenWidth;
235 out << " " << string(List,Start,End - Start) << endl;
236 Start = End + 1;
237 }
238 }
239
240 return false;
241 }
242 /*}}}*/
243 // ShowBroken - Debugging aide /*{{{*/
244 // ---------------------------------------------------------------------
245 /* This prints out the names of all the packages that are broken along
246 with the name of each each broken dependency and a quite version
247 description.
248
249 The output looks like:
250 The following packages have unmet dependencies:
251 exim: Depends: libc6 (>= 2.1.94) but 2.1.3-10 is to be installed
252 Depends: libldap2 (>= 2.0.2-2) but it is not going to be installed
253 Depends: libsasl7 but it is not going to be installed
254 */
255 void ShowBroken(ostream &out,CacheFile &Cache,bool Now)
256 {
257 out << _("The following packages have unmet dependencies:") << endl;
258 for (unsigned J = 0; J < Cache->Head().PackageCount; J++)
259 {
260 pkgCache::PkgIterator I(Cache,Cache.List[J]);
261
262 if (Now == true)
263 {
264 if (Cache[I].NowBroken() == false)
265 continue;
266 }
267 else
268 {
269 if (Cache[I].InstBroken() == false)
270 continue;
271 }
272
273 // Print out each package and the failed dependencies
274 out << " " << I.FullName(true) << " :";
275 unsigned const Indent = I.FullName(true).size() + 3;
276 bool First = true;
277 pkgCache::VerIterator Ver;
278
279 if (Now == true)
280 Ver = I.CurrentVer();
281 else
282 Ver = Cache[I].InstVerIter(Cache);
283
284 if (Ver.end() == true)
285 {
286 out << endl;
287 continue;
288 }
289
290 for (pkgCache::DepIterator D = Ver.DependsList(); D.end() == false;)
291 {
292 // Compute a single dependency element (glob or)
293 pkgCache::DepIterator Start;
294 pkgCache::DepIterator End;
295 D.GlobOr(Start,End); // advances D
296
297 if (Cache->IsImportantDep(End) == false)
298 continue;
299
300 if (Now == true)
301 {
302 if ((Cache[End] & pkgDepCache::DepGNow) == pkgDepCache::DepGNow)
303 continue;
304 }
305 else
306 {
307 if ((Cache[End] & pkgDepCache::DepGInstall) == pkgDepCache::DepGInstall)
308 continue;
309 }
310
311 bool FirstOr = true;
312 while (1)
313 {
314 if (First == false)
315 for (unsigned J = 0; J != Indent; J++)
316 out << ' ';
317 First = false;
318
319 if (FirstOr == false)
320 {
321 for (unsigned J = 0; J != strlen(End.DepType()) + 3; J++)
322 out << ' ';
323 }
324 else
325 out << ' ' << End.DepType() << ": ";
326 FirstOr = false;
327
328 out << Start.TargetPkg().FullName(true);
329
330 // Show a quick summary of the version requirements
331 if (Start.TargetVer() != 0)
332 out << " (" << Start.CompType() << " " << Start.TargetVer() << ")";
333
334 /* Show a summary of the target package if possible. In the case
335 of virtual packages we show nothing */
336 pkgCache::PkgIterator Targ = Start.TargetPkg();
337 if (Targ->ProvidesList == 0)
338 {
339 out << ' ';
340 pkgCache::VerIterator Ver = Cache[Targ].InstVerIter(Cache);
341 if (Now == true)
342 Ver = Targ.CurrentVer();
343
344 if (Ver.end() == false)
345 {
346 if (Now == true)
347 ioprintf(out,_("but %s is installed"),Ver.VerStr());
348 else
349 ioprintf(out,_("but %s is to be installed"),Ver.VerStr());
350 }
351 else
352 {
353 if (Cache[Targ].CandidateVerIter(Cache).end() == true)
354 {
355 if (Targ->ProvidesList == 0)
356 out << _("but it is not installable");
357 else
358 out << _("but it is a virtual package");
359 }
360 else
361 out << (Now?_("but it is not installed"):_("but it is not going to be installed"));
362 }
363 }
364
365 if (Start != End)
366 out << _(" or");
367 out << endl;
368
369 if (Start == End)
370 break;
371 ++Start;
372 }
373 }
374 }
375 }
376 /*}}}*/
377 // ShowNew - Show packages to newly install /*{{{*/
378 // ---------------------------------------------------------------------
379 /* */
380 void ShowNew(ostream &out,CacheFile &Cache)
381 {
382 /* Print out a list of packages that are going to be installed extra
383 to what the user asked */
384 string List;
385 string VersionsList;
386 for (unsigned J = 0; J < Cache->Head().PackageCount; J++)
387 {
388 pkgCache::PkgIterator I(Cache,Cache.List[J]);
389 if (Cache[I].NewInstall() == true) {
390 List += I.FullName(true) + " ";
391 VersionsList += string(Cache[I].CandVersion) + "\n";
392 }
393 }
394
395 ShowList(out,_("The following NEW packages will be installed:"),List,VersionsList);
396 }
397 /*}}}*/
398 // ShowDel - Show packages to delete /*{{{*/
399 // ---------------------------------------------------------------------
400 /* */
401 void ShowDel(ostream &out,CacheFile &Cache)
402 {
403 /* Print out a list of packages that are going to be removed extra
404 to what the user asked */
405 string List;
406 string VersionsList;
407 for (unsigned J = 0; J < Cache->Head().PackageCount; J++)
408 {
409 pkgCache::PkgIterator I(Cache,Cache.List[J]);
410 if (Cache[I].Delete() == true)
411 {
412 if ((Cache[I].iFlags & pkgDepCache::Purge) == pkgDepCache::Purge)
413 List += I.FullName(true) + "* ";
414 else
415 List += I.FullName(true) + " ";
416
417 VersionsList += string(Cache[I].CandVersion)+ "\n";
418 }
419 }
420
421 ShowList(out,_("The following packages will be REMOVED:"),List,VersionsList);
422 }
423 /*}}}*/
424 // ShowKept - Show kept packages /*{{{*/
425 // ---------------------------------------------------------------------
426 /* */
427 void ShowKept(ostream &out,CacheFile &Cache)
428 {
429 string List;
430 string VersionsList;
431 for (unsigned J = 0; J < Cache->Head().PackageCount; J++)
432 {
433 pkgCache::PkgIterator I(Cache,Cache.List[J]);
434
435 // Not interesting
436 if (Cache[I].Upgrade() == true || Cache[I].Upgradable() == false ||
437 I->CurrentVer == 0 || Cache[I].Delete() == true)
438 continue;
439
440 List += I.FullName(true) + " ";
441 VersionsList += string(Cache[I].CurVersion) + " => " + Cache[I].CandVersion + "\n";
442 }
443 ShowList(out,_("The following packages have been kept back:"),List,VersionsList);
444 }
445 /*}}}*/
446 // ShowUpgraded - Show upgraded packages /*{{{*/
447 // ---------------------------------------------------------------------
448 /* */
449 void ShowUpgraded(ostream &out,CacheFile &Cache)
450 {
451 string List;
452 string VersionsList;
453 for (unsigned J = 0; J < Cache->Head().PackageCount; J++)
454 {
455 pkgCache::PkgIterator I(Cache,Cache.List[J]);
456
457 // Not interesting
458 if (Cache[I].Upgrade() == false || Cache[I].NewInstall() == true)
459 continue;
460
461 List += I.FullName(true) + " ";
462 VersionsList += string(Cache[I].CurVersion) + " => " + Cache[I].CandVersion + "\n";
463 }
464 ShowList(out,_("The following packages will be upgraded:"),List,VersionsList);
465 }
466 /*}}}*/
467 // ShowDowngraded - Show downgraded packages /*{{{*/
468 // ---------------------------------------------------------------------
469 /* */
470 bool ShowDowngraded(ostream &out,CacheFile &Cache)
471 {
472 string List;
473 string VersionsList;
474 for (unsigned J = 0; J < Cache->Head().PackageCount; J++)
475 {
476 pkgCache::PkgIterator I(Cache,Cache.List[J]);
477
478 // Not interesting
479 if (Cache[I].Downgrade() == false || Cache[I].NewInstall() == true)
480 continue;
481
482 List += I.FullName(true) + " ";
483 VersionsList += string(Cache[I].CurVersion) + " => " + Cache[I].CandVersion + "\n";
484 }
485 return ShowList(out,_("The following packages will be DOWNGRADED:"),List,VersionsList);
486 }
487 /*}}}*/
488 // ShowHold - Show held but changed packages /*{{{*/
489 // ---------------------------------------------------------------------
490 /* */
491 bool ShowHold(ostream &out,CacheFile &Cache)
492 {
493 string List;
494 string VersionsList;
495 for (unsigned J = 0; J < Cache->Head().PackageCount; J++)
496 {
497 pkgCache::PkgIterator I(Cache,Cache.List[J]);
498 if (Cache[I].InstallVer != (pkgCache::Version *)I.CurrentVer() &&
499 I->SelectedState == pkgCache::State::Hold) {
500 List += I.FullName(true) + " ";
501 VersionsList += string(Cache[I].CurVersion) + " => " + Cache[I].CandVersion + "\n";
502 }
503 }
504
505 return ShowList(out,_("The following held packages will be changed:"),List,VersionsList);
506 }
507 /*}}}*/
508 // ShowEssential - Show an essential package warning /*{{{*/
509 // ---------------------------------------------------------------------
510 /* This prints out a warning message that is not to be ignored. It shows
511 all essential packages and their dependents that are to be removed.
512 It is insanely risky to remove the dependents of an essential package! */
513 bool ShowEssential(ostream &out,CacheFile &Cache)
514 {
515 string List;
516 string VersionsList;
517 bool *Added = new bool[Cache->Head().PackageCount];
518 for (unsigned int I = 0; I != Cache->Head().PackageCount; I++)
519 Added[I] = false;
520
521 for (unsigned J = 0; J < Cache->Head().PackageCount; J++)
522 {
523 pkgCache::PkgIterator I(Cache,Cache.List[J]);
524 if ((I->Flags & pkgCache::Flag::Essential) != pkgCache::Flag::Essential &&
525 (I->Flags & pkgCache::Flag::Important) != pkgCache::Flag::Important)
526 continue;
527
528 // The essential package is being removed
529 if (Cache[I].Delete() == true)
530 {
531 if (Added[I->ID] == false)
532 {
533 Added[I->ID] = true;
534 List += I.FullName(true) + " ";
535 //VersionsList += string(Cache[I].CurVersion) + "\n"; ???
536 }
537 }
538 else
539 continue;
540
541 if (I->CurrentVer == 0)
542 continue;
543
544 // Print out any essential package depenendents that are to be removed
545 for (pkgCache::DepIterator D = I.CurrentVer().DependsList(); D.end() == false; ++D)
546 {
547 // Skip everything but depends
548 if (D->Type != pkgCache::Dep::PreDepends &&
549 D->Type != pkgCache::Dep::Depends)
550 continue;
551
552 pkgCache::PkgIterator P = D.SmartTargetPkg();
553 if (Cache[P].Delete() == true)
554 {
555 if (Added[P->ID] == true)
556 continue;
557 Added[P->ID] = true;
558
559 char S[300];
560 snprintf(S,sizeof(S),_("%s (due to %s) "),P.FullName(true).c_str(),I.FullName(true).c_str());
561 List += S;
562 //VersionsList += "\n"; ???
563 }
564 }
565 }
566
567 delete [] Added;
568 return ShowList(out,_("WARNING: The following essential packages will be removed.\n"
569 "This should NOT be done unless you know exactly what you are doing!"),List,VersionsList);
570 }
571
572 /*}}}*/
573 // Stats - Show some statistics /*{{{*/
574 // ---------------------------------------------------------------------
575 /* */
576 void Stats(ostream &out,pkgDepCache &Dep)
577 {
578 unsigned long Upgrade = 0;
579 unsigned long Downgrade = 0;
580 unsigned long Install = 0;
581 unsigned long ReInstall = 0;
582 for (pkgCache::PkgIterator I = Dep.PkgBegin(); I.end() == false; ++I)
583 {
584 if (Dep[I].NewInstall() == true)
585 Install++;
586 else
587 {
588 if (Dep[I].Upgrade() == true)
589 Upgrade++;
590 else
591 if (Dep[I].Downgrade() == true)
592 Downgrade++;
593 }
594
595 if (Dep[I].Delete() == false && (Dep[I].iFlags & pkgDepCache::ReInstall) == pkgDepCache::ReInstall)
596 ReInstall++;
597 }
598
599 ioprintf(out,_("%lu upgraded, %lu newly installed, "),
600 Upgrade,Install);
601
602 if (ReInstall != 0)
603 ioprintf(out,_("%lu reinstalled, "),ReInstall);
604 if (Downgrade != 0)
605 ioprintf(out,_("%lu downgraded, "),Downgrade);
606
607 ioprintf(out,_("%lu to remove and %lu not upgraded.\n"),
608 Dep.DelCount(),Dep.KeepCount());
609
610 if (Dep.BadCount() != 0)
611 ioprintf(out,_("%lu not fully installed or removed.\n"),
612 Dep.BadCount());
613 }
614 /*}}}*/
615 // CacheSetHelperAPTGet - responsible for message telling from the CacheSets/*{{{*/
616 class CacheSetHelperAPTGet : public APT::CacheSetHelper {
617 /** \brief stream message should be printed to */
618 std::ostream &out;
619 /** \brief were things like Task or RegEx used to select packages? */
620 bool explicitlyNamed;
621
622 APT::PackageSet virtualPkgs;
623
624 public:
625 std::list<std::pair<pkgCache::VerIterator, std::string> > selectedByRelease;
626
627 CacheSetHelperAPTGet(std::ostream &out) : APT::CacheSetHelper(true), out(out) {
628 explicitlyNamed = true;
629 }
630
631 virtual void showTaskSelection(pkgCache::PkgIterator const &Pkg, string const &pattern) {
632 ioprintf(out, _("Note, selecting '%s' for task '%s'\n"),
633 Pkg.FullName(true).c_str(), pattern.c_str());
634 explicitlyNamed = false;
635 }
636 virtual void showRegExSelection(pkgCache::PkgIterator const &Pkg, string const &pattern) {
637 ioprintf(out, _("Note, selecting '%s' for regex '%s'\n"),
638 Pkg.FullName(true).c_str(), pattern.c_str());
639 explicitlyNamed = false;
640 }
641 virtual void showSelectedVersion(pkgCache::PkgIterator const &Pkg, pkgCache::VerIterator const Ver,
642 string const &ver, bool const verIsRel) {
643 if (ver == Ver.VerStr())
644 return;
645 selectedByRelease.push_back(make_pair(Ver, ver));
646 }
647
648 bool showVirtualPackageErrors(pkgCacheFile &Cache) {
649 if (virtualPkgs.empty() == true)
650 return true;
651 for (APT::PackageSet::const_iterator Pkg = virtualPkgs.begin();
652 Pkg != virtualPkgs.end(); ++Pkg) {
653 if (Pkg->ProvidesList != 0) {
654 ioprintf(c1out,_("Package %s is a virtual package provided by:\n"),
655 Pkg.FullName(true).c_str());
656
657 pkgCache::PrvIterator I = Pkg.ProvidesList();
658 unsigned short provider = 0;
659 for (; I.end() == false; ++I) {
660 pkgCache::PkgIterator Pkg = I.OwnerPkg();
661
662 if (Cache[Pkg].CandidateVerIter(Cache) == I.OwnerVer()) {
663 c1out << " " << Pkg.FullName(true) << " " << I.OwnerVer().VerStr();
664 if (Cache[Pkg].Install() == true && Cache[Pkg].NewInstall() == false)
665 c1out << _(" [Installed]");
666 c1out << endl;
667 ++provider;
668 }
669 }
670 // if we found no candidate which provide this package, show non-candidates
671 if (provider == 0)
672 for (I = Pkg.ProvidesList(); I.end() == false; ++I)
673 c1out << " " << I.OwnerPkg().FullName(true) << " " << I.OwnerVer().VerStr()
674 << _(" [Not candidate version]") << endl;
675 else
676 out << _("You should explicitly select one to install.") << endl;
677 } else {
678 ioprintf(c1out,
679 _("Package %s is not available, but is referred to by another package.\n"
680 "This may mean that the package is missing, has been obsoleted, or\n"
681 "is only available from another source\n"),Pkg.FullName(true).c_str());
682
683 string List;
684 string VersionsList;
685 SPtrArray<bool> Seen = new bool[Cache.GetPkgCache()->Head().PackageCount];
686 memset(Seen,0,Cache.GetPkgCache()->Head().PackageCount*sizeof(*Seen));
687 for (pkgCache::DepIterator Dep = Pkg.RevDependsList();
688 Dep.end() == false; ++Dep) {
689 if (Dep->Type != pkgCache::Dep::Replaces)
690 continue;
691 if (Seen[Dep.ParentPkg()->ID] == true)
692 continue;
693 Seen[Dep.ParentPkg()->ID] = true;
694 List += Dep.ParentPkg().FullName(true) + " ";
695 //VersionsList += string(Dep.ParentPkg().CurVersion) + "\n"; ???
696 }
697 ShowList(c1out,_("However the following packages replace it:"),List,VersionsList);
698 }
699 c1out << std::endl;
700 }
701 return false;
702 }
703
704 virtual pkgCache::VerIterator canNotFindCandidateVer(pkgCacheFile &Cache, pkgCache::PkgIterator const &Pkg) {
705 APT::VersionSet const verset = tryVirtualPackage(Cache, Pkg, APT::VersionSet::CANDIDATE);
706 if (verset.empty() == false)
707 return *(verset.begin());
708 else if (ShowError == true) {
709 _error->Error(_("Package '%s' has no installation candidate"),Pkg.FullName(true).c_str());
710 virtualPkgs.insert(Pkg);
711 }
712 return pkgCache::VerIterator(Cache, 0);
713 }
714
715 virtual pkgCache::VerIterator canNotFindNewestVer(pkgCacheFile &Cache, pkgCache::PkgIterator const &Pkg) {
716 APT::VersionSet const verset = tryVirtualPackage(Cache, Pkg, APT::VersionSet::NEWEST);
717 if (verset.empty() == false)
718 return *(verset.begin());
719 if (ShowError == true)
720 ioprintf(out, _("Virtual packages like '%s' can't be removed\n"), Pkg.FullName(true).c_str());
721 return pkgCache::VerIterator(Cache, 0);
722 }
723
724 APT::VersionSet tryVirtualPackage(pkgCacheFile &Cache, pkgCache::PkgIterator const &Pkg,
725 APT::VersionSet::Version const &select) {
726 /* This is a pure virtual package and there is a single available
727 candidate providing it. */
728 if (unlikely(Cache[Pkg].CandidateVer != 0) || Pkg->ProvidesList == 0)
729 return APT::VersionSet();
730
731 pkgCache::PkgIterator Prov;
732 bool found_one = false;
733 for (pkgCache::PrvIterator P = Pkg.ProvidesList(); P; ++P) {
734 pkgCache::VerIterator const PVer = P.OwnerVer();
735 pkgCache::PkgIterator const PPkg = PVer.ParentPkg();
736
737 /* Ignore versions that are not a candidate. */
738 if (Cache[PPkg].CandidateVer != PVer)
739 continue;
740
741 if (found_one == false) {
742 Prov = PPkg;
743 found_one = true;
744 } else if (PPkg != Prov) {
745 found_one = false; // we found at least two
746 break;
747 }
748 }
749
750 if (found_one == true) {
751 ioprintf(out, _("Note, selecting '%s' instead of '%s'\n"),
752 Prov.FullName(true).c_str(), Pkg.FullName(true).c_str());
753 return APT::VersionSet::FromPackage(Cache, Prov, select, *this);
754 }
755 return APT::VersionSet();
756 }
757
758 inline bool allPkgNamedExplicitly() const { return explicitlyNamed; }
759
760 };
761 /*}}}*/
762 // TryToInstall - Mark a package for installation /*{{{*/
763 struct TryToInstall {
764 pkgCacheFile* Cache;
765 pkgProblemResolver* Fix;
766 bool FixBroken;
767 unsigned long AutoMarkChanged;
768 APT::PackageSet doAutoInstallLater;
769
770 TryToInstall(pkgCacheFile &Cache, pkgProblemResolver *PM, bool const FixBroken) : Cache(&Cache), Fix(PM),
771 FixBroken(FixBroken), AutoMarkChanged(0) {};
772
773 void operator() (pkgCache::VerIterator const &Ver) {
774 pkgCache::PkgIterator Pkg = Ver.ParentPkg();
775
776 Cache->GetDepCache()->SetCandidateVersion(Ver);
777 pkgDepCache::StateCache &State = (*Cache)[Pkg];
778
779 // Handle the no-upgrade case
780 if (_config->FindB("APT::Get::upgrade",true) == false && Pkg->CurrentVer != 0)
781 ioprintf(c1out,_("Skipping %s, it is already installed and upgrade is not set.\n"),
782 Pkg.FullName(true).c_str());
783 // Ignore request for install if package would be new
784 else if (_config->FindB("APT::Get::Only-Upgrade", false) == true && Pkg->CurrentVer == 0)
785 ioprintf(c1out,_("Skipping %s, it is not installed and only upgrades are requested.\n"),
786 Pkg.FullName(true).c_str());
787 else {
788 if (Fix != NULL) {
789 Fix->Clear(Pkg);
790 Fix->Protect(Pkg);
791 }
792 Cache->GetDepCache()->MarkInstall(Pkg,false);
793
794 if (State.Install() == false) {
795 if (_config->FindB("APT::Get::ReInstall",false) == true) {
796 if (Pkg->CurrentVer == 0 || Pkg.CurrentVer().Downloadable() == false)
797 ioprintf(c1out,_("Reinstallation of %s is not possible, it cannot be downloaded.\n"),
798 Pkg.FullName(true).c_str());
799 else
800 Cache->GetDepCache()->SetReInstall(Pkg, true);
801 } else
802 ioprintf(c1out,_("%s is already the newest version.\n"),
803 Pkg.FullName(true).c_str());
804 }
805
806 // Install it with autoinstalling enabled (if we not respect the minial
807 // required deps or the policy)
808 if (FixBroken == false)
809 doAutoInstallLater.insert(Pkg);
810 }
811
812 // see if we need to fix the auto-mark flag
813 // e.g. apt-get install foo
814 // where foo is marked automatic
815 if (State.Install() == false &&
816 (State.Flags & pkgCache::Flag::Auto) &&
817 _config->FindB("APT::Get::ReInstall",false) == false &&
818 _config->FindB("APT::Get::Only-Upgrade",false) == false &&
819 _config->FindB("APT::Get::Download-Only",false) == false)
820 {
821 ioprintf(c1out,_("%s set to manually installed.\n"),
822 Pkg.FullName(true).c_str());
823 Cache->GetDepCache()->MarkAuto(Pkg,false);
824 AutoMarkChanged++;
825 }
826 }
827
828 bool propergateReleaseCandiateSwitching(std::list<std::pair<pkgCache::VerIterator, std::string> > start, std::ostream &out)
829 {
830 for (std::list<std::pair<pkgCache::VerIterator, std::string> >::const_iterator s = start.begin();
831 s != start.end(); ++s)
832 Cache->GetDepCache()->SetCandidateVersion(s->first);
833
834 bool Success = true;
835 std::list<std::pair<pkgCache::VerIterator, pkgCache::VerIterator> > Changed;
836 for (std::list<std::pair<pkgCache::VerIterator, std::string> >::const_iterator s = start.begin();
837 s != start.end(); ++s)
838 {
839 Changed.push_back(std::make_pair(s->first, pkgCache::VerIterator(*Cache)));
840 // We continue here even if it failed to enhance the ShowBroken output
841 Success &= Cache->GetDepCache()->SetCandidateRelease(s->first, s->second, Changed);
842 }
843 for (std::list<std::pair<pkgCache::VerIterator, pkgCache::VerIterator> >::const_iterator c = Changed.begin();
844 c != Changed.end(); ++c)
845 {
846 if (c->second.end() == true)
847 ioprintf(out, _("Selected version '%s' (%s) for '%s'\n"),
848 c->first.VerStr(), c->first.RelStr().c_str(), c->first.ParentPkg().FullName(true).c_str());
849 else if (c->first.ParentPkg()->Group != c->second.ParentPkg()->Group)
850 {
851 pkgCache::VerIterator V = (*Cache)[c->first.ParentPkg()].CandidateVerIter(*Cache);
852 ioprintf(out, _("Selected version '%s' (%s) for '%s' because of '%s'\n"), V.VerStr(),
853 V.RelStr().c_str(), V.ParentPkg().FullName(true).c_str(), c->second.ParentPkg().FullName(true).c_str());
854 }
855 }
856 return Success;
857 }
858
859 void doAutoInstall() {
860 for (APT::PackageSet::const_iterator P = doAutoInstallLater.begin();
861 P != doAutoInstallLater.end(); ++P) {
862 pkgDepCache::StateCache &State = (*Cache)[P];
863 if (State.InstBroken() == false && State.InstPolicyBroken() == false)
864 continue;
865 Cache->GetDepCache()->MarkInstall(P, true);
866 }
867 doAutoInstallLater.clear();
868 }
869 };
870 /*}}}*/
871 // TryToRemove - Mark a package for removal /*{{{*/
872 struct TryToRemove {
873 pkgCacheFile* Cache;
874 pkgProblemResolver* Fix;
875 bool PurgePkgs;
876
877 TryToRemove(pkgCacheFile &Cache, pkgProblemResolver *PM) : Cache(&Cache), Fix(PM),
878 PurgePkgs(_config->FindB("APT::Get::Purge", false)) {};
879
880 void operator() (pkgCache::VerIterator const &Ver)
881 {
882 pkgCache::PkgIterator Pkg = Ver.ParentPkg();
883
884 if (Fix != NULL)
885 {
886 Fix->Clear(Pkg);
887 Fix->Protect(Pkg);
888 Fix->Remove(Pkg);
889 }
890
891 if ((Pkg->CurrentVer == 0 && PurgePkgs == false) ||
892 (PurgePkgs == true && Pkg->CurrentState == pkgCache::State::NotInstalled))
893 {
894 ioprintf(c1out,_("Package %s is not installed, so not removed\n"),Pkg.FullName(true).c_str());
895 // MarkInstall refuses to install packages on hold
896 Pkg->SelectedState = pkgCache::State::Hold;
897 }
898 else
899 Cache->GetDepCache()->MarkDelete(Pkg, PurgePkgs);
900 }
901 };
902 /*}}}*/
903 // CacheFile::NameComp - QSort compare by name /*{{{*/
904 // ---------------------------------------------------------------------
905 /* */
906 pkgCache *CacheFile::SortCache = 0;
907 int CacheFile::NameComp(const void *a,const void *b)
908 {
909 if (*(pkgCache::Package **)a == 0 || *(pkgCache::Package **)b == 0)
910 return *(pkgCache::Package **)a - *(pkgCache::Package **)b;
911
912 const pkgCache::Package &A = **(pkgCache::Package **)a;
913 const pkgCache::Package &B = **(pkgCache::Package **)b;
914
915 return strcmp(SortCache->StrP + A.Name,SortCache->StrP + B.Name);
916 }
917 /*}}}*/
918 // CacheFile::Sort - Sort by name /*{{{*/
919 // ---------------------------------------------------------------------
920 /* */
921 void CacheFile::Sort()
922 {
923 delete [] List;
924 List = new pkgCache::Package *[Cache->Head().PackageCount];
925 memset(List,0,sizeof(*List)*Cache->Head().PackageCount);
926 pkgCache::PkgIterator I = Cache->PkgBegin();
927 for (;I.end() != true; ++I)
928 List[I->ID] = I;
929
930 SortCache = *this;
931 qsort(List,Cache->Head().PackageCount,sizeof(*List),NameComp);
932 }
933 /*}}}*/
934 // CacheFile::CheckDeps - Open the cache file /*{{{*/
935 // ---------------------------------------------------------------------
936 /* This routine generates the caches and then opens the dependency cache
937 and verifies that the system is OK. */
938 bool CacheFile::CheckDeps(bool AllowBroken)
939 {
940 bool FixBroken = _config->FindB("APT::Get::Fix-Broken",false);
941
942 if (_error->PendingError() == true)
943 return false;
944
945 // Check that the system is OK
946 if (DCache->DelCount() != 0 || DCache->InstCount() != 0)
947 return _error->Error("Internal error, non-zero counts");
948
949 // Apply corrections for half-installed packages
950 if (pkgApplyStatus(*DCache) == false)
951 return false;
952
953 if (_config->FindB("APT::Get::Fix-Policy-Broken",false) == true)
954 {
955 FixBroken = true;
956 if ((DCache->PolicyBrokenCount() > 0))
957 {
958 // upgrade all policy-broken packages with ForceImportantDeps=True
959 for (pkgCache::PkgIterator I = Cache->PkgBegin(); !I.end(); ++I)
960 if ((*DCache)[I].NowPolicyBroken() == true)
961 DCache->MarkInstall(I,true,0, false, true);
962 }
963 }
964
965 // Nothing is broken
966 if (DCache->BrokenCount() == 0 || AllowBroken == true)
967 return true;
968
969 // Attempt to fix broken things
970 if (FixBroken == true)
971 {
972 c1out << _("Correcting dependencies...") << flush;
973 if (pkgFixBroken(*DCache) == false || DCache->BrokenCount() != 0)
974 {
975 c1out << _(" failed.") << endl;
976 ShowBroken(c1out,*this,true);
977
978 return _error->Error(_("Unable to correct dependencies"));
979 }
980 if (pkgMinimizeUpgrade(*DCache) == false)
981 return _error->Error(_("Unable to minimize the upgrade set"));
982
983 c1out << _(" Done") << endl;
984 }
985 else
986 {
987 c1out << _("You might want to run 'apt-get -f install' to correct these.") << endl;
988 ShowBroken(c1out,*this,true);
989
990 return _error->Error(_("Unmet dependencies. Try using -f."));
991 }
992
993 return true;
994 }
995 /*}}}*/
996 // CheckAuth - check if each download comes form a trusted source /*{{{*/
997 // ---------------------------------------------------------------------
998 /* */
999 static bool CheckAuth(pkgAcquire& Fetcher)
1000 {
1001 string UntrustedList;
1002 for (pkgAcquire::ItemIterator I = Fetcher.ItemsBegin(); I < Fetcher.ItemsEnd(); ++I)
1003 {
1004 if (!(*I)->IsTrusted())
1005 {
1006 UntrustedList += string((*I)->ShortDesc()) + " ";
1007 }
1008 }
1009
1010 if (UntrustedList == "")
1011 {
1012 return true;
1013 }
1014
1015 ShowList(c2out,_("WARNING: The following packages cannot be authenticated!"),UntrustedList,"");
1016
1017 if (_config->FindB("APT::Get::AllowUnauthenticated",false) == true)
1018 {
1019 c2out << _("Authentication warning overridden.\n");
1020 return true;
1021 }
1022
1023 if (_config->FindI("quiet",0) < 2
1024 && _config->FindB("APT::Get::Assume-Yes",false) == false)
1025 {
1026 c2out << _("Install these packages without verification [y/N]? ") << flush;
1027 if (!YnPrompt(false))
1028 return _error->Error(_("Some packages could not be authenticated"));
1029
1030 return true;
1031 }
1032 else if (_config->FindB("APT::Get::Force-Yes",false) == true)
1033 {
1034 return true;
1035 }
1036
1037 return _error->Error(_("There are problems and -y was used without --force-yes"));
1038 }
1039 /*}}}*/
1040 // InstallPackages - Actually download and install the packages /*{{{*/
1041 // ---------------------------------------------------------------------
1042 /* This displays the informative messages describing what is going to
1043 happen and then calls the download routines */
1044 bool InstallPackages(CacheFile &Cache,bool ShwKept,bool Ask = true,
1045 bool Safety = true)
1046 {
1047 if (_config->FindB("APT::Get::Purge",false) == true)
1048 {
1049 pkgCache::PkgIterator I = Cache->PkgBegin();
1050 for (; I.end() == false; ++I)
1051 {
1052 if (I.Purge() == false && Cache[I].Mode == pkgDepCache::ModeDelete)
1053 Cache->MarkDelete(I,true);
1054 }
1055 }
1056
1057 bool Fail = false;
1058 bool Essential = false;
1059
1060 // Show all the various warning indicators
1061 ShowDel(c1out,Cache);
1062 ShowNew(c1out,Cache);
1063 if (ShwKept == true)
1064 ShowKept(c1out,Cache);
1065 Fail |= !ShowHold(c1out,Cache);
1066 if (_config->FindB("APT::Get::Show-Upgraded",true) == true)
1067 ShowUpgraded(c1out,Cache);
1068 Fail |= !ShowDowngraded(c1out,Cache);
1069 if (_config->FindB("APT::Get::Download-Only",false) == false)
1070 Essential = !ShowEssential(c1out,Cache);
1071 Fail |= Essential;
1072 Stats(c1out,Cache);
1073
1074 // Sanity check
1075 if (Cache->BrokenCount() != 0)
1076 {
1077 ShowBroken(c1out,Cache,false);
1078 return _error->Error(_("Internal error, InstallPackages was called with broken packages!"));
1079 }
1080
1081 if (Cache->DelCount() == 0 && Cache->InstCount() == 0 &&
1082 Cache->BadCount() == 0)
1083 return true;
1084
1085 // No remove flag
1086 if (Cache->DelCount() != 0 && _config->FindB("APT::Get::Remove",true) == false)
1087 return _error->Error(_("Packages need to be removed but remove is disabled."));
1088
1089 // Run the simulator ..
1090 if (_config->FindB("APT::Get::Simulate") == true)
1091 {
1092 pkgSimulate PM(Cache);
1093 int status_fd = _config->FindI("APT::Status-Fd",-1);
1094 pkgPackageManager::OrderResult Res = PM.DoInstall(status_fd);
1095 if (Res == pkgPackageManager::Failed)
1096 return false;
1097 if (Res != pkgPackageManager::Completed)
1098 return _error->Error(_("Internal error, Ordering didn't finish"));
1099 return true;
1100 }
1101
1102 // Create the text record parser
1103 pkgRecords Recs(Cache);
1104 if (_error->PendingError() == true)
1105 return false;
1106
1107 // Create the download object
1108 pkgAcquire Fetcher;
1109 AcqTextStatus Stat(ScreenWidth,_config->FindI("quiet",0));
1110 if (_config->FindB("APT::Get::Print-URIs", false) == true)
1111 {
1112 // force a hashsum for compatibility reasons
1113 _config->CndSet("Acquire::ForceHash", "md5sum");
1114 }
1115 else if (Fetcher.Setup(&Stat, _config->FindDir("Dir::Cache::Archives")) == false)
1116 return false;
1117
1118 // Read the source list
1119 if (Cache.BuildSourceList() == false)
1120 return false;
1121 pkgSourceList *List = Cache.GetSourceList();
1122
1123 // Create the package manager and prepare to download
1124 SPtr<pkgPackageManager> PM= _system->CreatePM(Cache);
1125 if (PM->GetArchives(&Fetcher,List,&Recs) == false ||
1126 _error->PendingError() == true)
1127 return false;
1128
1129 // Display statistics
1130 unsigned long long FetchBytes = Fetcher.FetchNeeded();
1131 unsigned long long FetchPBytes = Fetcher.PartialPresent();
1132 unsigned long long DebBytes = Fetcher.TotalNeeded();
1133 if (DebBytes != Cache->DebSize())
1134 {
1135 c0out << DebBytes << ',' << Cache->DebSize() << endl;
1136 c0out << _("How odd.. The sizes didn't match, email apt@packages.debian.org") << endl;
1137 }
1138
1139 // Number of bytes
1140 if (DebBytes != FetchBytes)
1141 //TRANSLATOR: The required space between number and unit is already included
1142 // in the replacement strings, so %sB will be correctly translate in e.g. 1,5 MB
1143 ioprintf(c1out,_("Need to get %sB/%sB of archives.\n"),
1144 SizeToStr(FetchBytes).c_str(),SizeToStr(DebBytes).c_str());
1145 else if (DebBytes != 0)
1146 //TRANSLATOR: The required space between number and unit is already included
1147 // in the replacement string, so %sB will be correctly translate in e.g. 1,5 MB
1148 ioprintf(c1out,_("Need to get %sB of archives.\n"),
1149 SizeToStr(DebBytes).c_str());
1150
1151 // Size delta
1152 if (Cache->UsrSize() >= 0)
1153 //TRANSLATOR: The required space between number and unit is already included
1154 // in the replacement string, so %sB will be correctly translate in e.g. 1,5 MB
1155 ioprintf(c1out,_("After this operation, %sB of additional disk space will be used.\n"),
1156 SizeToStr(Cache->UsrSize()).c_str());
1157 else
1158 //TRANSLATOR: The required space between number and unit is already included
1159 // in the replacement string, so %sB will be correctly translate in e.g. 1,5 MB
1160 ioprintf(c1out,_("After this operation, %sB disk space will be freed.\n"),
1161 SizeToStr(-1*Cache->UsrSize()).c_str());
1162
1163 if (_error->PendingError() == true)
1164 return false;
1165
1166 /* Check for enough free space, but only if we are actually going to
1167 download */
1168 if (_config->FindB("APT::Get::Print-URIs") == false &&
1169 _config->FindB("APT::Get::Download",true) == true)
1170 {
1171 struct statvfs Buf;
1172 string OutputDir = _config->FindDir("Dir::Cache::Archives");
1173 if (statvfs(OutputDir.c_str(),&Buf) != 0) {
1174 if (errno == EOVERFLOW)
1175 return _error->WarningE("statvfs",_("Couldn't determine free space in %s"),
1176 OutputDir.c_str());
1177 else
1178 return _error->Errno("statvfs",_("Couldn't determine free space in %s"),
1179 OutputDir.c_str());
1180 } else if (unsigned(Buf.f_bfree) < (FetchBytes - FetchPBytes)/Buf.f_bsize)
1181 {
1182 struct statfs Stat;
1183 if (statfs(OutputDir.c_str(),&Stat) != 0
1184 #if HAVE_STRUCT_STATFS_F_TYPE
1185 || unsigned(Stat.f_type) != RAMFS_MAGIC
1186 #endif
1187 )
1188 return _error->Error(_("You don't have enough free space in %s."),
1189 OutputDir.c_str());
1190 }
1191 }
1192
1193 // Fail safe check
1194 if (_config->FindI("quiet",0) >= 2 ||
1195 _config->FindB("APT::Get::Assume-Yes",false) == true)
1196 {
1197 if (Fail == true && _config->FindB("APT::Get::Force-Yes",false) == false)
1198 return _error->Error(_("There are problems and -y was used without --force-yes"));
1199 }
1200
1201 if (Essential == true && Safety == true)
1202 {
1203 if (_config->FindB("APT::Get::Trivial-Only",false) == true)
1204 return _error->Error(_("Trivial Only specified but this is not a trivial operation."));
1205
1206 const char *Prompt = _("Yes, do as I say!");
1207 ioprintf(c2out,
1208 _("You are about to do something potentially harmful.\n"
1209 "To continue type in the phrase '%s'\n"
1210 " ?] "),Prompt);
1211 c2out << flush;
1212 if (AnalPrompt(Prompt) == false)
1213 {
1214 c2out << _("Abort.") << endl;
1215 exit(1);
1216 }
1217 }
1218 else
1219 {
1220 // Prompt to continue
1221 if (Ask == true || Fail == true)
1222 {
1223 if (_config->FindB("APT::Get::Trivial-Only",false) == true)
1224 return _error->Error(_("Trivial Only specified but this is not a trivial operation."));
1225
1226 if (_config->FindI("quiet",0) < 2 &&
1227 _config->FindB("APT::Get::Assume-Yes",false) == false)
1228 {
1229 c2out << _("Do you want to continue [Y/n]? ") << flush;
1230
1231 if (YnPrompt() == false)
1232 {
1233 c2out << _("Abort.") << endl;
1234 exit(1);
1235 }
1236 }
1237 }
1238 }
1239
1240 // Just print out the uris an exit if the --print-uris flag was used
1241 if (_config->FindB("APT::Get::Print-URIs") == true)
1242 {
1243 pkgAcquire::UriIterator I = Fetcher.UriBegin();
1244 for (; I != Fetcher.UriEnd(); ++I)
1245 cout << '\'' << I->URI << "' " << flNotDir(I->Owner->DestFile) << ' ' <<
1246 I->Owner->FileSize << ' ' << I->Owner->HashSum() << endl;
1247 return true;
1248 }
1249
1250 if (!CheckAuth(Fetcher))
1251 return false;
1252
1253 /* Unlock the dpkg lock if we are not going to be doing an install
1254 after. */
1255 if (_config->FindB("APT::Get::Download-Only",false) == true)
1256 _system->UnLock();
1257
1258 // Run it
1259 while (1)
1260 {
1261 bool Transient = false;
1262 if (_config->FindB("APT::Get::Download",true) == false)
1263 {
1264 for (pkgAcquire::ItemIterator I = Fetcher.ItemsBegin(); I < Fetcher.ItemsEnd();)
1265 {
1266 if ((*I)->Local == true)
1267 {
1268 ++I;
1269 continue;
1270 }
1271
1272 // Close the item and check if it was found in cache
1273 (*I)->Finished();
1274 if ((*I)->Complete == false)
1275 Transient = true;
1276
1277 // Clear it out of the fetch list
1278 delete *I;
1279 I = Fetcher.ItemsBegin();
1280 }
1281 }
1282
1283 if (Fetcher.Run() == pkgAcquire::Failed)
1284 return false;
1285
1286 // Print out errors
1287 bool Failed = false;
1288 for (pkgAcquire::ItemIterator I = Fetcher.ItemsBegin(); I != Fetcher.ItemsEnd(); ++I)
1289 {
1290 if ((*I)->Status == pkgAcquire::Item::StatDone &&
1291 (*I)->Complete == true)
1292 continue;
1293
1294 if ((*I)->Status == pkgAcquire::Item::StatIdle)
1295 {
1296 Transient = true;
1297 // Failed = true;
1298 continue;
1299 }
1300
1301 fprintf(stderr,_("Failed to fetch %s %s\n"),(*I)->DescURI().c_str(),
1302 (*I)->ErrorText.c_str());
1303 Failed = true;
1304 }
1305
1306 /* If we are in no download mode and missing files and there were
1307 'failures' then the user must specify -m. Furthermore, there
1308 is no such thing as a transient error in no-download mode! */
1309 if (Transient == true &&
1310 _config->FindB("APT::Get::Download",true) == false)
1311 {
1312 Transient = false;
1313 Failed = true;
1314 }
1315
1316 if (_config->FindB("APT::Get::Download-Only",false) == true)
1317 {
1318 if (Failed == true && _config->FindB("APT::Get::Fix-Missing",false) == false)
1319 return _error->Error(_("Some files failed to download"));
1320 c1out << _("Download complete and in download only mode") << endl;
1321 return true;
1322 }
1323
1324 if (Failed == true && _config->FindB("APT::Get::Fix-Missing",false) == false)
1325 {
1326 return _error->Error(_("Unable to fetch some archives, maybe run apt-get update or try with --fix-missing?"));
1327 }
1328
1329 if (Transient == true && Failed == true)
1330 return _error->Error(_("--fix-missing and media swapping is not currently supported"));
1331
1332 // Try to deal with missing package files
1333 if (Failed == true && PM->FixMissing() == false)
1334 {
1335 cerr << _("Unable to correct missing packages.") << endl;
1336 return _error->Error(_("Aborting install."));
1337 }
1338
1339 _system->UnLock();
1340 int status_fd = _config->FindI("APT::Status-Fd",-1);
1341 pkgPackageManager::OrderResult Res = PM->DoInstall(status_fd);
1342 if (Res == pkgPackageManager::Failed || _error->PendingError() == true)
1343 return false;
1344 if (Res == pkgPackageManager::Completed)
1345 break;
1346
1347 // Reload the fetcher object and loop again for media swapping
1348 Fetcher.Shutdown();
1349 if (PM->GetArchives(&Fetcher,List,&Recs) == false)
1350 return false;
1351
1352 _system->Lock();
1353 }
1354
1355 std::set<std::string> const disappearedPkgs = PM->GetDisappearedPackages();
1356 if (disappearedPkgs.empty() == true)
1357 return true;
1358
1359 string disappear;
1360 for (std::set<std::string>::const_iterator d = disappearedPkgs.begin();
1361 d != disappearedPkgs.end(); ++d)
1362 disappear.append(*d).append(" ");
1363
1364 ShowList(c1out, P_("The following package disappeared from your system as\n"
1365 "all files have been overwritten by other packages:",
1366 "The following packages disappeared from your system as\n"
1367 "all files have been overwritten by other packages:", disappearedPkgs.size()), disappear, "");
1368 c0out << _("Note: This is done automatic and on purpose by dpkg.") << std::endl;
1369
1370 return true;
1371 }
1372 /*}}}*/
1373 // TryToInstallBuildDep - Try to install a single package /*{{{*/
1374 // ---------------------------------------------------------------------
1375 /* This used to be inlined in DoInstall, but with the advent of regex package
1376 name matching it was split out.. */
1377 bool TryToInstallBuildDep(pkgCache::PkgIterator Pkg,pkgCacheFile &Cache,
1378 pkgProblemResolver &Fix,bool Remove,bool BrokenFix,
1379 bool AllowFail = true)
1380 {
1381 if (Cache[Pkg].CandidateVer == 0 && Pkg->ProvidesList != 0)
1382 {
1383 CacheSetHelperAPTGet helper(c1out);
1384 helper.showErrors(AllowFail == false);
1385 pkgCache::VerIterator Ver = helper.canNotFindNewestVer(Cache, Pkg);
1386 if (Ver.end() == false)
1387 Pkg = Ver.ParentPkg();
1388 else if (helper.showVirtualPackageErrors(Cache) == false)
1389 return AllowFail;
1390 }
1391
1392 if (_config->FindB("Debug::BuildDeps",false) == true)
1393 {
1394 if (Remove == true)
1395 cout << " Trying to remove " << Pkg << endl;
1396 else
1397 cout << " Trying to install " << Pkg << endl;
1398 }
1399
1400 if (Remove == true)
1401 {
1402 TryToRemove RemoveAction(Cache, &Fix);
1403 RemoveAction(Pkg.VersionList());
1404 } else if (Cache[Pkg].CandidateVer != 0) {
1405 TryToInstall InstallAction(Cache, &Fix, BrokenFix);
1406 InstallAction(Cache[Pkg].CandidateVerIter(Cache));
1407 InstallAction.doAutoInstall();
1408 } else
1409 return AllowFail;
1410
1411 return true;
1412 }
1413 /*}}}*/
1414 // FindSrc - Find a source record /*{{{*/
1415 // ---------------------------------------------------------------------
1416 /* */
1417 pkgSrcRecords::Parser *FindSrc(const char *Name,pkgRecords &Recs,
1418 pkgSrcRecords &SrcRecs,string &Src,
1419 pkgDepCache &Cache)
1420 {
1421 string VerTag;
1422 string DefRel = _config->Find("APT::Default-Release");
1423 string TmpSrc = Name;
1424
1425 // extract the version/release from the pkgname
1426 const size_t found = TmpSrc.find_last_of("/=");
1427 if (found != string::npos) {
1428 if (TmpSrc[found] == '/')
1429 DefRel = TmpSrc.substr(found+1);
1430 else
1431 VerTag = TmpSrc.substr(found+1);
1432 TmpSrc = TmpSrc.substr(0,found);
1433 }
1434
1435 /* Lookup the version of the package we would install if we were to
1436 install a version and determine the source package name, then look
1437 in the archive for a source package of the same name. */
1438 bool MatchSrcOnly = _config->FindB("APT::Get::Only-Source");
1439 const pkgCache::PkgIterator Pkg = Cache.FindPkg(TmpSrc);
1440 if (MatchSrcOnly == false && Pkg.end() == false)
1441 {
1442 if(VerTag.empty() == false || DefRel.empty() == false)
1443 {
1444 bool fuzzy = false;
1445 // we have a default release, try to locate the pkg. we do it like
1446 // this because GetCandidateVer() will not "downgrade", that means
1447 // "apt-get source -t stable apt" won't work on a unstable system
1448 for (pkgCache::VerIterator Ver = Pkg.VersionList();; ++Ver)
1449 {
1450 // try first only exact matches, later fuzzy matches
1451 if (Ver.end() == true)
1452 {
1453 if (fuzzy == true)
1454 break;
1455 fuzzy = true;
1456 Ver = Pkg.VersionList();
1457 // exit right away from the Pkg.VersionList() loop if we
1458 // don't have any versions
1459 if (Ver.end() == true)
1460 break;
1461 }
1462 // We match against a concrete version (or a part of this version)
1463 if (VerTag.empty() == false &&
1464 (fuzzy == true || Cache.VS().CmpVersion(VerTag, Ver.VerStr()) != 0) && // exact match
1465 (fuzzy == false || strncmp(VerTag.c_str(), Ver.VerStr(), VerTag.size()) != 0)) // fuzzy match
1466 continue;
1467
1468 for (pkgCache::VerFileIterator VF = Ver.FileList();
1469 VF.end() == false; ++VF)
1470 {
1471 /* If this is the status file, and the current version is not the
1472 version in the status file (ie it is not installed, or somesuch)
1473 then it is not a candidate for installation, ever. This weeds
1474 out bogus entries that may be due to config-file states, or
1475 other. */
1476 if ((VF.File()->Flags & pkgCache::Flag::NotSource) ==
1477 pkgCache::Flag::NotSource && Pkg.CurrentVer() != Ver)
1478 continue;
1479
1480 // or we match against a release
1481 if(VerTag.empty() == false ||
1482 (VF.File().Archive() != 0 && VF.File().Archive() == DefRel) ||
1483 (VF.File().Codename() != 0 && VF.File().Codename() == DefRel))
1484 {
1485 pkgRecords::Parser &Parse = Recs.Lookup(VF);
1486 Src = Parse.SourcePkg();
1487 // no SourcePkg name, so it is the "binary" name
1488 if (Src.empty() == true)
1489 Src = TmpSrc;
1490 // the Version we have is possibly fuzzy or includes binUploads,
1491 // so we use the Version of the SourcePkg (empty if same as package)
1492 VerTag = Parse.SourceVer();
1493 if (VerTag.empty() == true)
1494 VerTag = Ver.VerStr();
1495 break;
1496 }
1497 }
1498 if (Src.empty() == false)
1499 break;
1500 }
1501 if (Src.empty() == true)
1502 {
1503 // Sources files have no codename information
1504 if (VerTag.empty() == true && DefRel.empty() == false)
1505 {
1506 _error->Error(_("Ignore unavailable target release '%s' of package '%s'"), DefRel.c_str(), TmpSrc.c_str());
1507 return 0;
1508 }
1509 }
1510 }
1511 if (Src.empty() == true)
1512 {
1513 // if we don't have found a fitting package yet so we will
1514 // choose a good candidate and proceed with that.
1515 // Maybe we will find a source later on with the right VerTag
1516 pkgCache::VerIterator Ver = Cache.GetCandidateVer(Pkg);
1517 if (Ver.end() == false)
1518 {
1519 pkgRecords::Parser &Parse = Recs.Lookup(Ver.FileList());
1520 Src = Parse.SourcePkg();
1521 if (VerTag.empty() == true)
1522 VerTag = Parse.SourceVer();
1523 }
1524 }
1525 }
1526
1527 if (Src.empty() == true)
1528 Src = TmpSrc;
1529 else
1530 {
1531 /* if we have a source pkg name, make sure to only search
1532 for srcpkg names, otherwise apt gets confused if there
1533 is a binary package "pkg1" and a source package "pkg1"
1534 with the same name but that comes from different packages */
1535 MatchSrcOnly = true;
1536 if (Src != TmpSrc)
1537 {
1538 ioprintf(c1out, _("Picking '%s' as source package instead of '%s'\n"), Src.c_str(), TmpSrc.c_str());
1539 }
1540 }
1541
1542 // The best hit
1543 pkgSrcRecords::Parser *Last = 0;
1544 unsigned long Offset = 0;
1545 string Version;
1546
1547 /* Iterate over all of the hits, which includes the resulting
1548 binary packages in the search */
1549 pkgSrcRecords::Parser *Parse;
1550 while (true)
1551 {
1552 SrcRecs.Restart();
1553 while ((Parse = SrcRecs.Find(Src.c_str(), MatchSrcOnly)) != 0)
1554 {
1555 const string Ver = Parse->Version();
1556
1557 // Ignore all versions which doesn't fit
1558 if (VerTag.empty() == false &&
1559 Cache.VS().CmpVersion(VerTag, Ver) != 0) // exact match
1560 continue;
1561
1562 // Newer version or an exact match? Save the hit
1563 if (Last == 0 || Cache.VS().CmpVersion(Version,Ver) < 0) {
1564 Last = Parse;
1565 Offset = Parse->Offset();
1566 Version = Ver;
1567 }
1568
1569 // was the version check above an exact match? If so, we don't need to look further
1570 if (VerTag.empty() == false && VerTag.size() == Ver.size())
1571 break;
1572 }
1573 if (Last != 0 || VerTag.empty() == true)
1574 break;
1575 //if (VerTag.empty() == false && Last == 0)
1576 _error->Error(_("Ignore unavailable version '%s' of package '%s'"), VerTag.c_str(), TmpSrc.c_str());
1577 return 0;
1578 }
1579
1580 if (Last == 0 || Last->Jump(Offset) == false)
1581 return 0;
1582
1583 return Last;
1584 }
1585 /*}}}*/
1586 // DoUpdate - Update the package lists /*{{{*/
1587 // ---------------------------------------------------------------------
1588 /* */
1589 bool DoUpdate(CommandLine &CmdL)
1590 {
1591 if (CmdL.FileSize() != 1)
1592 return _error->Error(_("The update command takes no arguments"));
1593
1594 CacheFile Cache;
1595
1596 // Get the source list
1597 if (Cache.BuildSourceList() == false)
1598 return false;
1599 pkgSourceList *List = Cache.GetSourceList();
1600
1601 // Create the progress
1602 AcqTextStatus Stat(ScreenWidth,_config->FindI("quiet",0));
1603
1604 // Just print out the uris an exit if the --print-uris flag was used
1605 if (_config->FindB("APT::Get::Print-URIs") == true)
1606 {
1607 // force a hashsum for compatibility reasons
1608 _config->CndSet("Acquire::ForceHash", "md5sum");
1609
1610 // get a fetcher
1611 pkgAcquire Fetcher;
1612 if (Fetcher.Setup(&Stat) == false)
1613 return false;
1614
1615 // Populate it with the source selection and get all Indexes
1616 // (GetAll=true)
1617 if (List->GetIndexes(&Fetcher,true) == false)
1618 return false;
1619
1620 pkgAcquire::UriIterator I = Fetcher.UriBegin();
1621 for (; I != Fetcher.UriEnd(); ++I)
1622 cout << '\'' << I->URI << "' " << flNotDir(I->Owner->DestFile) << ' ' <<
1623 I->Owner->FileSize << ' ' << I->Owner->HashSum() << endl;
1624 return true;
1625 }
1626
1627 // do the work
1628 if (_config->FindB("APT::Get::Download",true) == true)
1629 ListUpdate(Stat, *List);
1630
1631 // Rebuild the cache.
1632 pkgCacheFile::RemoveCaches();
1633 if (Cache.BuildCaches() == false)
1634 return false;
1635
1636 return true;
1637 }
1638 /*}}}*/
1639 // DoAutomaticRemove - Remove all automatic unused packages /*{{{*/
1640 // ---------------------------------------------------------------------
1641 /* Remove unused automatic packages */
1642 bool DoAutomaticRemove(CacheFile &Cache)
1643 {
1644 bool Debug = _config->FindI("Debug::pkgAutoRemove",false);
1645 bool doAutoRemove = _config->FindB("APT::Get::AutomaticRemove", false);
1646 bool hideAutoRemove = _config->FindB("APT::Get::HideAutoRemove");
1647
1648 pkgDepCache::ActionGroup group(*Cache);
1649 if(Debug)
1650 std::cout << "DoAutomaticRemove()" << std::endl;
1651
1652 if (doAutoRemove == true &&
1653 _config->FindB("APT::Get::Remove",true) == false)
1654 {
1655 c1out << _("We are not supposed to delete stuff, can't start "
1656 "AutoRemover") << std::endl;
1657 return false;
1658 }
1659
1660 bool purgePkgs = _config->FindB("APT::Get::Purge", false);
1661 bool smallList = (hideAutoRemove == false &&
1662 strcasecmp(_config->Find("APT::Get::HideAutoRemove","").c_str(),"small") == 0);
1663
1664 string autoremovelist, autoremoveversions;
1665 unsigned long autoRemoveCount = 0;
1666 APT::PackageSet tooMuch;
1667 // look over the cache to see what can be removed
1668 for (pkgCache::PkgIterator Pkg = Cache->PkgBegin(); ! Pkg.end(); ++Pkg)
1669 {
1670 if (Cache[Pkg].Garbage)
1671 {
1672 if(Pkg.CurrentVer() != 0 || Cache[Pkg].Install())
1673 if(Debug)
1674 std::cout << "We could delete %s" << Pkg.FullName(true).c_str() << std::endl;
1675
1676 if (doAutoRemove)
1677 {
1678 if(Pkg.CurrentVer() != 0 &&
1679 Pkg->CurrentState != pkgCache::State::ConfigFiles)
1680 Cache->MarkDelete(Pkg, purgePkgs);
1681 else
1682 Cache->MarkKeep(Pkg, false, false);
1683 }
1684 else
1685 {
1686 // if the package is a new install and already garbage we don't need to
1687 // install it in the first place, so nuke it instead of show it
1688 if (Cache[Pkg].Install() == true && Pkg.CurrentVer() == 0)
1689 {
1690 if (Pkg.CandVersion() != 0)
1691 tooMuch.insert(Pkg);
1692 Cache->MarkDelete(Pkg, false);
1693 }
1694 // only show stuff in the list that is not yet marked for removal
1695 else if(hideAutoRemove == false && Cache[Pkg].Delete() == false)
1696 {
1697 ++autoRemoveCount;
1698 // we don't need to fill the strings if we don't need them
1699 if (smallList == false)
1700 {
1701 autoremovelist += Pkg.FullName(true) + " ";
1702 autoremoveversions += string(Cache[Pkg].CandVersion) + "\n";
1703 }
1704 }
1705 }
1706 }
1707 }
1708
1709 // we could have removed a new dependency of a garbage package,
1710 // so check if a reverse depends is broken and if so install it again.
1711 if (tooMuch.empty() == false && (Cache->BrokenCount() != 0 || Cache->PolicyBrokenCount() != 0))
1712 {
1713 bool Changed;
1714 do {
1715 Changed = false;
1716 for (APT::PackageSet::const_iterator Pkg = tooMuch.begin();
1717 Pkg != tooMuch.end() && Changed == false; ++Pkg)
1718 {
1719 APT::PackageSet too;
1720 too.insert(Pkg);
1721 for (pkgCache::PrvIterator Prv = Cache[Pkg].CandidateVerIter(Cache).ProvidesList();
1722 Prv.end() == false; ++Prv)
1723 too.insert(Prv.ParentPkg());
1724 for (APT::PackageSet::const_iterator P = too.begin();
1725 P != too.end() && Changed == false; ++P) {
1726 for (pkgCache::DepIterator R = P.RevDependsList();
1727 R.end() == false; ++R)
1728 {
1729 if (R.IsNegative() == true ||
1730 Cache->IsImportantDep(R) == false)
1731 continue;
1732 pkgCache::PkgIterator N = R.ParentPkg();
1733 if (N.end() == true || (N->CurrentVer == 0 && (*Cache)[N].Install() == false))
1734 continue;
1735 if (Debug == true)
1736 std::clog << "Save " << Pkg << " as another installed garbage package depends on it" << std::endl;
1737 Cache->MarkInstall(Pkg, false);
1738 if (hideAutoRemove == false)
1739 {
1740 ++autoRemoveCount;
1741 if (smallList == false)
1742 {
1743 autoremovelist += Pkg.FullName(true) + " ";
1744 autoremoveversions += string(Cache[Pkg].CandVersion) + "\n";
1745 }
1746 }
1747 tooMuch.erase(Pkg);
1748 Changed = true;
1749 break;
1750 }
1751 }
1752 }
1753 } while (Changed == true);
1754 }
1755
1756 // Now see if we had destroyed anything (if we had done anything)
1757 if (Cache->BrokenCount() != 0)
1758 {
1759 c1out << _("Hmm, seems like the AutoRemover destroyed something which really\n"
1760 "shouldn't happen. Please file a bug report against apt.") << endl;
1761 c1out << endl;
1762 c1out << _("The following information may help to resolve the situation:") << endl;
1763 c1out << endl;
1764 ShowBroken(c1out,Cache,false);
1765
1766 return _error->Error(_("Internal Error, AutoRemover broke stuff"));
1767 }
1768
1769 // if we don't remove them, we should show them!
1770 if (doAutoRemove == false && (autoremovelist.empty() == false || autoRemoveCount != 0))
1771 {
1772 if (smallList == false)
1773 ShowList(c1out, P_("The following package was automatically installed and is no longer required:",
1774 "The following packages were automatically installed and are no longer required:",
1775 autoRemoveCount), autoremovelist, autoremoveversions);
1776 else
1777 ioprintf(c1out, P_("%lu package was automatically installed and is no longer required.\n",
1778 "%lu packages were automatically installed and are no longer required.\n", autoRemoveCount), autoRemoveCount);
1779 c1out << _("Use 'apt-get autoremove' to remove them.") << std::endl;
1780 }
1781 return true;
1782 }
1783 /*}}}*/
1784 // DoUpgrade - Upgrade all packages /*{{{*/
1785 // ---------------------------------------------------------------------
1786 /* Upgrade all packages without installing new packages or erasing old
1787 packages */
1788 bool DoUpgrade(CommandLine &CmdL)
1789 {
1790 CacheFile Cache;
1791 if (Cache.OpenForInstall() == false || Cache.CheckDeps() == false)
1792 return false;
1793
1794 // Do the upgrade
1795 if (pkgAllUpgrade(Cache) == false)
1796 {
1797 ShowBroken(c1out,Cache,false);
1798 return _error->Error(_("Internal error, AllUpgrade broke stuff"));
1799 }
1800
1801 return InstallPackages(Cache,true);
1802 }
1803 /*}}}*/
1804 // DoInstall - Install packages from the command line /*{{{*/
1805 // ---------------------------------------------------------------------
1806 /* Install named packages */
1807 bool DoInstall(CommandLine &CmdL)
1808 {
1809 CacheFile Cache;
1810 if (Cache.OpenForInstall() == false ||
1811 Cache.CheckDeps(CmdL.FileSize() != 1) == false)
1812 return false;
1813
1814 // Enter the special broken fixing mode if the user specified arguments
1815 bool BrokenFix = false;
1816 if (Cache->BrokenCount() != 0)
1817 BrokenFix = true;
1818
1819 pkgProblemResolver* Fix = NULL;
1820 if (_config->FindB("APT::Get::CallResolver", true) == true)
1821 Fix = new pkgProblemResolver(Cache);
1822
1823 static const unsigned short MOD_REMOVE = 1;
1824 static const unsigned short MOD_INSTALL = 2;
1825
1826 unsigned short fallback = MOD_INSTALL;
1827 if (strcasecmp(CmdL.FileList[0],"remove") == 0)
1828 fallback = MOD_REMOVE;
1829 else if (strcasecmp(CmdL.FileList[0], "purge") == 0)
1830 {
1831 _config->Set("APT::Get::Purge", true);
1832 fallback = MOD_REMOVE;
1833 }
1834 else if (strcasecmp(CmdL.FileList[0], "autoremove") == 0)
1835 {
1836 _config->Set("APT::Get::AutomaticRemove", "true");
1837 fallback = MOD_REMOVE;
1838 }
1839
1840 std::list<APT::VersionSet::Modifier> mods;
1841 mods.push_back(APT::VersionSet::Modifier(MOD_INSTALL, "+",
1842 APT::VersionSet::Modifier::POSTFIX, APT::VersionSet::CANDIDATE));
1843 mods.push_back(APT::VersionSet::Modifier(MOD_REMOVE, "-",
1844 APT::VersionSet::Modifier::POSTFIX, APT::VersionSet::NEWEST));
1845 CacheSetHelperAPTGet helper(c0out);
1846 std::map<unsigned short, APT::VersionSet> verset = APT::VersionSet::GroupedFromCommandLine(Cache,
1847 CmdL.FileList + 1, mods, fallback, helper);
1848
1849 if (_error->PendingError() == true)
1850 {
1851 helper.showVirtualPackageErrors(Cache);
1852 if (Fix != NULL)
1853 delete Fix;
1854 return false;
1855 }
1856
1857 unsigned short const order[] = { MOD_REMOVE, MOD_INSTALL, 0 };
1858
1859 TryToInstall InstallAction(Cache, Fix, BrokenFix);
1860 TryToRemove RemoveAction(Cache, Fix);
1861
1862 // new scope for the ActionGroup
1863 {
1864 pkgDepCache::ActionGroup group(Cache);
1865
1866 for (unsigned short i = 0; order[i] != 0; ++i)
1867 {
1868 if (order[i] == MOD_INSTALL)
1869 InstallAction = std::for_each(verset[MOD_INSTALL].begin(), verset[MOD_INSTALL].end(), InstallAction);
1870 else if (order[i] == MOD_REMOVE)
1871 RemoveAction = std::for_each(verset[MOD_REMOVE].begin(), verset[MOD_REMOVE].end(), RemoveAction);
1872 }
1873
1874 if (Fix != NULL && _config->FindB("APT::Get::AutoSolving", true) == true)
1875 {
1876 for (unsigned short i = 0; order[i] != 0; ++i)
1877 {
1878 if (order[i] != MOD_INSTALL)
1879 continue;
1880 InstallAction.propergateReleaseCandiateSwitching(helper.selectedByRelease, c0out);
1881 InstallAction.doAutoInstall();
1882 }
1883 }
1884
1885 if (_error->PendingError() == true)
1886 {
1887 if (Fix != NULL)
1888 delete Fix;
1889 return false;
1890 }
1891
1892 /* If we are in the Broken fixing mode we do not attempt to fix the
1893 problems. This is if the user invoked install without -f and gave
1894 packages */
1895 if (BrokenFix == true && Cache->BrokenCount() != 0)
1896 {
1897 c1out << _("You might want to run 'apt-get -f install' to correct these:") << endl;
1898 ShowBroken(c1out,Cache,false);
1899 if (Fix != NULL)
1900 delete Fix;
1901 return _error->Error(_("Unmet dependencies. Try 'apt-get -f install' with no packages (or specify a solution)."));
1902 }
1903
1904 if (Fix != NULL)
1905 {
1906 // Call the scored problem resolver
1907 Fix->InstallProtect();
1908 Fix->Resolve(true);
1909 delete Fix;
1910 }
1911
1912 // Now we check the state of the packages,
1913 if (Cache->BrokenCount() != 0)
1914 {
1915 c1out <<
1916 _("Some packages could not be installed. This may mean that you have\n"
1917 "requested an impossible situation or if you are using the unstable\n"
1918 "distribution that some required packages have not yet been created\n"
1919 "or been moved out of Incoming.") << endl;
1920 /*
1921 if (Packages == 1)
1922 {
1923 c1out << endl;
1924 c1out <<
1925 _("Since you only requested a single operation it is extremely likely that\n"
1926 "the package is simply not installable and a bug report against\n"
1927 "that package should be filed.") << endl;
1928 }
1929 */
1930
1931 c1out << _("The following information may help to resolve the situation:") << endl;
1932 c1out << endl;
1933 ShowBroken(c1out,Cache,false);
1934 if (_error->PendingError() == true)
1935 return false;
1936 else
1937 return _error->Error(_("Broken packages"));
1938 }
1939 }
1940 if (!DoAutomaticRemove(Cache))
1941 return false;
1942
1943 /* Print out a list of packages that are going to be installed extra
1944 to what the user asked */
1945 if (Cache->InstCount() != verset[MOD_INSTALL].size())
1946 {
1947 string List;
1948 string VersionsList;
1949 for (unsigned J = 0; J < Cache->Head().PackageCount; J++)
1950 {
1951 pkgCache::PkgIterator I(Cache,Cache.List[J]);
1952 if ((*Cache)[I].Install() == false)
1953 continue;
1954 pkgCache::VerIterator Cand = Cache[I].CandidateVerIter(Cache);
1955
1956 if (verset[MOD_INSTALL].find(Cand) != verset[MOD_INSTALL].end())
1957 continue;
1958
1959 List += I.FullName(true) + " ";
1960 VersionsList += string(Cache[I].CandVersion) + "\n";
1961 }
1962
1963 ShowList(c1out,_("The following extra packages will be installed:"),List,VersionsList);
1964 }
1965
1966 /* Print out a list of suggested and recommended packages */
1967 {
1968 string SuggestsList, RecommendsList, List;
1969 string SuggestsVersions, RecommendsVersions;
1970 for (unsigned J = 0; J < Cache->Head().PackageCount; J++)
1971 {
1972 pkgCache::PkgIterator Pkg(Cache,Cache.List[J]);
1973
1974 /* Just look at the ones we want to install */
1975 if ((*Cache)[Pkg].Install() == false)
1976 continue;
1977
1978 // get the recommends/suggests for the candidate ver
1979 pkgCache::VerIterator CV = (*Cache)[Pkg].CandidateVerIter(*Cache);
1980 for (pkgCache::DepIterator D = CV.DependsList(); D.end() == false; )
1981 {
1982 pkgCache::DepIterator Start;
1983 pkgCache::DepIterator End;
1984 D.GlobOr(Start,End); // advances D
1985
1986 // FIXME: we really should display a or-group as a or-group to the user
1987 // the problem is that ShowList is incapable of doing this
1988 string RecommendsOrList,RecommendsOrVersions;
1989 string SuggestsOrList,SuggestsOrVersions;
1990 bool foundInstalledInOrGroup = false;
1991 for(;;)
1992 {
1993 /* Skip if package is installed already, or is about to be */
1994 string target = Start.TargetPkg().FullName(true) + " ";
1995 pkgCache::PkgIterator const TarPkg = Start.TargetPkg();
1996 if (TarPkg->SelectedState == pkgCache::State::Install ||
1997 TarPkg->SelectedState == pkgCache::State::Hold ||
1998 Cache[Start.TargetPkg()].Install())
1999 {
2000 foundInstalledInOrGroup=true;
2001 break;
2002 }
2003
2004 /* Skip if we already saw it */
2005 if (int(SuggestsList.find(target)) != -1 || int(RecommendsList.find(target)) != -1)
2006 {
2007 foundInstalledInOrGroup=true;
2008 break;
2009 }
2010
2011 // this is a dep on a virtual pkg, check if any package that provides it
2012 // should be installed
2013 if(Start.TargetPkg().ProvidesList() != 0)
2014 {
2015 pkgCache::PrvIterator I = Start.TargetPkg().ProvidesList();
2016 for (; I.end() == false; ++I)
2017 {
2018 pkgCache::PkgIterator Pkg = I.OwnerPkg();
2019 if (Cache[Pkg].CandidateVerIter(Cache) == I.OwnerVer() &&
2020 Pkg.CurrentVer() != 0)
2021 foundInstalledInOrGroup=true;
2022 }
2023 }
2024
2025 if (Start->Type == pkgCache::Dep::Suggests)
2026 {
2027 SuggestsOrList += target;
2028 SuggestsOrVersions += string(Cache[Start.TargetPkg()].CandVersion) + "\n";
2029 }
2030
2031 if (Start->Type == pkgCache::Dep::Recommends)
2032 {
2033 RecommendsOrList += target;
2034 RecommendsOrVersions += string(Cache[Start.TargetPkg()].CandVersion) + "\n";
2035 }
2036
2037 if (Start >= End)
2038 break;
2039 ++Start;
2040 }
2041
2042 if(foundInstalledInOrGroup == false)
2043 {
2044 RecommendsList += RecommendsOrList;
2045 RecommendsVersions += RecommendsOrVersions;
2046 SuggestsList += SuggestsOrList;
2047 SuggestsVersions += SuggestsOrVersions;
2048 }
2049
2050 }
2051 }
2052
2053 ShowList(c1out,_("Suggested packages:"),SuggestsList,SuggestsVersions);
2054 ShowList(c1out,_("Recommended packages:"),RecommendsList,RecommendsVersions);
2055
2056 }
2057
2058 // if nothing changed in the cache, but only the automark information
2059 // we write the StateFile here, otherwise it will be written in
2060 // cache.commit()
2061 if (InstallAction.AutoMarkChanged > 0 &&
2062 Cache->DelCount() == 0 && Cache->InstCount() == 0 &&
2063 Cache->BadCount() == 0 &&
2064 _config->FindB("APT::Get::Simulate",false) == false)
2065 Cache->writeStateFile(NULL);
2066
2067 // See if we need to prompt
2068 // FIXME: check if really the packages in the set are going to be installed
2069 if (Cache->InstCount() == verset[MOD_INSTALL].size() && Cache->DelCount() == 0)
2070 return InstallPackages(Cache,false,false);
2071
2072 return InstallPackages(Cache,false);
2073 }
2074 /*}}}*/
2075 /* mark packages as automatically/manually installed. {{{*/
2076 bool DoMarkAuto(CommandLine &CmdL)
2077 {
2078 bool Action = true;
2079 int AutoMarkChanged = 0;
2080 OpTextProgress progress;
2081 CacheFile Cache;
2082 if (Cache.Open() == false)
2083 return false;
2084
2085 if (strcasecmp(CmdL.FileList[0],"markauto") == 0)
2086 Action = true;
2087 else if (strcasecmp(CmdL.FileList[0],"unmarkauto") == 0)
2088 Action = false;
2089
2090 for (const char **I = CmdL.FileList + 1; *I != 0; I++)
2091 {
2092 const char *S = *I;
2093 // Locate the package
2094 pkgCache::PkgIterator Pkg = Cache->FindPkg(S);
2095 if (Pkg.end() == true) {
2096 return _error->Error(_("Couldn't find package %s"),S);
2097 }
2098 else
2099 {
2100 if (!Action)
2101 ioprintf(c1out,_("%s set to manually installed.\n"), Pkg.Name());
2102 else
2103 ioprintf(c1out,_("%s set to automatically installed.\n"),
2104 Pkg.Name());
2105
2106 Cache->MarkAuto(Pkg,Action);
2107 AutoMarkChanged++;
2108 }
2109 }
2110
2111 _error->Notice(_("This command is deprecated. Please use 'apt-mark auto' and 'apt-mark manual' instead."));
2112
2113 if (AutoMarkChanged && ! _config->FindB("APT::Get::Simulate",false))
2114 return Cache->writeStateFile(NULL);
2115 return false;
2116 }
2117 /*}}}*/
2118 // DoDistUpgrade - Automatic smart upgrader /*{{{*/
2119 // ---------------------------------------------------------------------
2120 /* Intelligent upgrader that will install and remove packages at will */
2121 bool DoDistUpgrade(CommandLine &CmdL)
2122 {
2123 CacheFile Cache;
2124 if (Cache.OpenForInstall() == false || Cache.CheckDeps() == false)
2125 return false;
2126
2127 c0out << _("Calculating upgrade... ") << flush;
2128 if (pkgDistUpgrade(*Cache) == false)
2129 {
2130 c0out << _("Failed") << endl;
2131 ShowBroken(c1out,Cache,false);
2132 return false;
2133 }
2134
2135 c0out << _("Done") << endl;
2136
2137 return InstallPackages(Cache,true);
2138 }
2139 /*}}}*/
2140 // DoDSelectUpgrade - Do an upgrade by following dselects selections /*{{{*/
2141 // ---------------------------------------------------------------------
2142 /* Follows dselect's selections */
2143 bool DoDSelectUpgrade(CommandLine &CmdL)
2144 {
2145 CacheFile Cache;
2146 if (Cache.OpenForInstall() == false || Cache.CheckDeps() == false)
2147 return false;
2148
2149 pkgDepCache::ActionGroup group(Cache);
2150
2151 // Install everything with the install flag set
2152 pkgCache::PkgIterator I = Cache->PkgBegin();
2153 for (;I.end() != true; ++I)
2154 {
2155 /* Install the package only if it is a new install, the autoupgrader
2156 will deal with the rest */
2157 if (I->SelectedState == pkgCache::State::Install)
2158 Cache->MarkInstall(I,false);
2159 }
2160
2161 /* Now install their deps too, if we do this above then order of
2162 the status file is significant for | groups */
2163 for (I = Cache->PkgBegin();I.end() != true; ++I)
2164 {
2165 /* Install the package only if it is a new install, the autoupgrader
2166 will deal with the rest */
2167 if (I->SelectedState == pkgCache::State::Install)
2168 Cache->MarkInstall(I,true);
2169 }
2170
2171 // Apply erasures now, they override everything else.
2172 for (I = Cache->PkgBegin();I.end() != true; ++I)
2173 {
2174 // Remove packages
2175 if (I->SelectedState == pkgCache::State::DeInstall ||
2176 I->SelectedState == pkgCache::State::Purge)
2177 Cache->MarkDelete(I,I->SelectedState == pkgCache::State::Purge);
2178 }
2179
2180 /* Resolve any problems that dselect created, allupgrade cannot handle
2181 such things. We do so quite agressively too.. */
2182 if (Cache->BrokenCount() != 0)
2183 {
2184 pkgProblemResolver Fix(Cache);
2185
2186 // Hold back held packages.
2187 if (_config->FindB("APT::Ignore-Hold",false) == false)
2188 {
2189 for (pkgCache::PkgIterator I = Cache->PkgBegin(); I.end() == false; ++I)
2190 {
2191 if (I->SelectedState == pkgCache::State::Hold)
2192 {
2193 Fix.Protect(I);
2194 Cache->MarkKeep(I);
2195 }
2196 }
2197 }
2198
2199 if (Fix.Resolve() == false)
2200 {
2201 ShowBroken(c1out,Cache,false);
2202 return _error->Error(_("Internal error, problem resolver broke stuff"));
2203 }
2204 }
2205
2206 // Now upgrade everything
2207 if (pkgAllUpgrade(Cache) == false)
2208 {
2209 ShowBroken(c1out,Cache,false);
2210 return _error->Error(_("Internal error, problem resolver broke stuff"));
2211 }
2212
2213 return InstallPackages(Cache,false);
2214 }
2215 /*}}}*/
2216 // DoClean - Remove download archives /*{{{*/
2217 // ---------------------------------------------------------------------
2218 /* */
2219 bool DoClean(CommandLine &CmdL)
2220 {
2221 std::string const archivedir = _config->FindDir("Dir::Cache::archives");
2222 std::string const pkgcache = _config->FindFile("Dir::cache::pkgcache");
2223 std::string const srcpkgcache = _config->FindFile("Dir::cache::srcpkgcache");
2224
2225 if (_config->FindB("APT::Get::Simulate") == true)
2226 {
2227 cout << "Del " << archivedir << "* " << archivedir << "partial/*"<< endl
2228 << "Del " << pkgcache << " " << srcpkgcache << endl;
2229 return true;
2230 }
2231
2232 // Lock the archive directory
2233 FileFd Lock;
2234 if (_config->FindB("Debug::NoLocking",false) == false)
2235 {
2236 Lock.Fd(GetLock(archivedir + "lock"));
2237 if (_error->PendingError() == true)
2238 return _error->Error(_("Unable to lock the download directory"));
2239 }
2240
2241 pkgAcquire Fetcher;
2242 Fetcher.Clean(archivedir);
2243 Fetcher.Clean(archivedir + "partial/");
2244
2245 pkgCacheFile::RemoveCaches();
2246
2247 return true;
2248 }
2249 /*}}}*/
2250 // DoAutoClean - Smartly remove downloaded archives /*{{{*/
2251 // ---------------------------------------------------------------------
2252 /* This is similar to clean but it only purges things that cannot be
2253 downloaded, that is old versions of cached packages. */
2254 class LogCleaner : public pkgArchiveCleaner
2255 {
2256 protected:
2257 virtual void Erase(const char *File,string Pkg,string Ver,struct stat &St)
2258 {
2259 c1out << "Del " << Pkg << " " << Ver << " [" << SizeToStr(St.st_size) << "B]" << endl;
2260
2261 if (_config->FindB("APT::Get::Simulate") == false)
2262 unlink(File);
2263 };
2264 };
2265
2266 bool DoAutoClean(CommandLine &CmdL)
2267 {
2268 // Lock the archive directory
2269 FileFd Lock;
2270 if (_config->FindB("Debug::NoLocking",false) == false)
2271 {
2272 Lock.Fd(GetLock(_config->FindDir("Dir::Cache::Archives") + "lock"));
2273 if (_error->PendingError() == true)
2274 return _error->Error(_("Unable to lock the download directory"));
2275 }
2276
2277 CacheFile Cache;
2278 if (Cache.Open() == false)
2279 return false;
2280
2281 LogCleaner Cleaner;
2282
2283 return Cleaner.Go(_config->FindDir("Dir::Cache::archives"),*Cache) &&
2284 Cleaner.Go(_config->FindDir("Dir::Cache::archives") + "partial/",*Cache);
2285 }
2286 /*}}}*/
2287 // DoDownload - download a binary /*{{{*/
2288 // ---------------------------------------------------------------------
2289 bool DoDownload(CommandLine &CmdL)
2290 {
2291 CacheFile Cache;
2292 if (Cache.ReadOnlyOpen() == false)
2293 return false;
2294
2295 APT::CacheSetHelper helper(c0out);
2296 APT::VersionSet verset = APT::VersionSet::FromCommandLine(Cache,
2297 CmdL.FileList + 1, APT::VersionSet::CANDIDATE, helper);
2298
2299 if (verset.empty() == true)
2300 return false;
2301
2302 pkgAcquire Fetcher;
2303 AcqTextStatus Stat(ScreenWidth, _config->FindI("quiet",0));
2304 if (_config->FindB("APT::Get::Print-URIs") == false)
2305 Fetcher.Setup(&Stat);
2306
2307 pkgRecords Recs(Cache);
2308 pkgSourceList *SrcList = Cache.GetSourceList();
2309 for (APT::VersionSet::const_iterator Ver = verset.begin();
2310 Ver != verset.end();
2311 ++Ver)
2312 {
2313 string descr;
2314 // get the right version
2315 pkgCache::PkgIterator Pkg = Ver.ParentPkg();
2316 pkgRecords::Parser &rec=Recs.Lookup(Ver.FileList());
2317 pkgCache::VerFileIterator Vf = Ver.FileList();
2318 if (Vf.end() == true)
2319 return _error->Error("Can not find VerFile");
2320 pkgCache::PkgFileIterator F = Vf.File();
2321 pkgIndexFile *index;
2322 if(SrcList->FindIndex(F, index) == false)
2323 return _error->Error("FindIndex failed");
2324 string uri = index->ArchiveURI(rec.FileName());
2325 strprintf(descr, _("Downloading %s %s"), Pkg.Name(), Ver.VerStr());
2326 // get the most appropriate hash
2327 HashString hash;
2328 if (rec.SHA512Hash() != "")
2329 hash = HashString("sha512", rec.SHA512Hash());
2330 if (rec.SHA256Hash() != "")
2331 hash = HashString("sha256", rec.SHA256Hash());
2332 else if (rec.SHA1Hash() != "")
2333 hash = HashString("sha1", rec.SHA1Hash());
2334 else if (rec.MD5Hash() != "")
2335 hash = HashString("md5", rec.MD5Hash());
2336 // get the file
2337 new pkgAcqFile(&Fetcher, uri, hash.toStr(), (*Ver)->Size, descr, Pkg.Name(), ".");
2338 }
2339
2340 // Just print out the uris and exit if the --print-uris flag was used
2341 if (_config->FindB("APT::Get::Print-URIs") == true)
2342 {
2343 pkgAcquire::UriIterator I = Fetcher.UriBegin();
2344 for (; I != Fetcher.UriEnd(); ++I)
2345 cout << '\'' << I->URI << "' " << flNotDir(I->Owner->DestFile) << ' ' <<
2346 I->Owner->FileSize << ' ' << I->Owner->HashSum() << endl;
2347 return true;
2348 }
2349
2350 return (Fetcher.Run() == pkgAcquire::Continue);
2351 }
2352 /*}}}*/
2353 // DoCheck - Perform the check operation /*{{{*/
2354 // ---------------------------------------------------------------------
2355 /* Opening automatically checks the system, this command is mostly used
2356 for debugging */
2357 bool DoCheck(CommandLine &CmdL)
2358 {
2359 CacheFile Cache;
2360 Cache.Open();
2361 Cache.CheckDeps();
2362
2363 return true;
2364 }
2365 /*}}}*/
2366 // DoSource - Fetch a source archive /*{{{*/
2367 // ---------------------------------------------------------------------
2368 /* Fetch souce packages */
2369 struct DscFile
2370 {
2371 string Package;
2372 string Version;
2373 string Dsc;
2374 };
2375
2376 bool DoSource(CommandLine &CmdL)
2377 {
2378 CacheFile Cache;
2379 if (Cache.Open(false) == false)
2380 return false;
2381
2382 if (CmdL.FileSize() <= 1)
2383 return _error->Error(_("Must specify at least one package to fetch source for"));
2384
2385 // Read the source list
2386 if (Cache.BuildSourceList() == false)
2387 return false;
2388 pkgSourceList *List = Cache.GetSourceList();
2389
2390 // Create the text record parsers
2391 pkgRecords Recs(Cache);
2392 pkgSrcRecords SrcRecs(*List);
2393 if (_error->PendingError() == true)
2394 return false;
2395
2396 // Create the download object
2397 AcqTextStatus Stat(ScreenWidth,_config->FindI("quiet",0));
2398 pkgAcquire Fetcher;
2399 Fetcher.SetLog(&Stat);
2400
2401 DscFile *Dsc = new DscFile[CmdL.FileSize()];
2402
2403 // insert all downloaded uris into this set to avoid downloading them
2404 // twice
2405 set<string> queued;
2406
2407 // Diff only mode only fetches .diff files
2408 bool const diffOnly = _config->FindB("APT::Get::Diff-Only", false);
2409 // Tar only mode only fetches .tar files
2410 bool const tarOnly = _config->FindB("APT::Get::Tar-Only", false);
2411 // Dsc only mode only fetches .dsc files
2412 bool const dscOnly = _config->FindB("APT::Get::Dsc-Only", false);
2413
2414 // Load the requestd sources into the fetcher
2415 unsigned J = 0;
2416 for (const char **I = CmdL.FileList + 1; *I != 0; I++, J++)
2417 {
2418 string Src;
2419 pkgSrcRecords::Parser *Last = FindSrc(*I,Recs,SrcRecs,Src,*Cache);
2420
2421 if (Last == 0) {
2422 delete[] Dsc;
2423 return _error->Error(_("Unable to find a source package for %s"),Src.c_str());
2424 }
2425
2426 string srec = Last->AsStr();
2427 string::size_type pos = srec.find("\nVcs-");
2428 while (pos != string::npos)
2429 {
2430 pos += strlen("\nVcs-");
2431 string vcs = srec.substr(pos,srec.find(":",pos)-pos);
2432 if(vcs == "Browser")
2433 {
2434 pos = srec.find("\nVcs-", pos);
2435 continue;
2436 }
2437 pos += vcs.length()+2;
2438 string::size_type epos = srec.find("\n", pos);
2439 string uri = srec.substr(pos,epos-pos).c_str();
2440 ioprintf(c1out, _("NOTICE: '%s' packaging is maintained in "
2441 "the '%s' version control system at:\n"
2442 "%s\n"),
2443 Src.c_str(), vcs.c_str(), uri.c_str());
2444 if(vcs == "Bzr")
2445 ioprintf(c1out,_("Please use:\n"
2446 "bzr get %s\n"
2447 "to retrieve the latest (possibly unreleased) "
2448 "updates to the package.\n"),
2449 uri.c_str());
2450 break;
2451 }
2452
2453 // Back track
2454 vector<pkgSrcRecords::File> Lst;
2455 if (Last->Files(Lst) == false) {
2456 delete[] Dsc;
2457 return false;
2458 }
2459
2460 // Load them into the fetcher
2461 for (vector<pkgSrcRecords::File>::const_iterator I = Lst.begin();
2462 I != Lst.end(); ++I)
2463 {
2464 // Try to guess what sort of file it is we are getting.
2465 if (I->Type == "dsc")
2466 {
2467 Dsc[J].Package = Last->Package();
2468 Dsc[J].Version = Last->Version();
2469 Dsc[J].Dsc = flNotDir(I->Path);
2470 }
2471
2472 // Handle the only options so that multiple can be used at once
2473 if (diffOnly == true || tarOnly == true || dscOnly == true)
2474 {
2475 if ((diffOnly == true && I->Type == "diff") ||
2476 (tarOnly == true && I->Type == "tar") ||
2477 (dscOnly == true && I->Type == "dsc"))
2478 ; // Fine, we want this file downloaded
2479 else
2480 continue;
2481 }
2482
2483 // don't download the same uri twice (should this be moved to
2484 // the fetcher interface itself?)
2485 if(queued.find(Last->Index().ArchiveURI(I->Path)) != queued.end())
2486 continue;
2487 queued.insert(Last->Index().ArchiveURI(I->Path));
2488
2489 // check if we have a file with that md5 sum already localy
2490 if(!I->MD5Hash.empty() && FileExists(flNotDir(I->Path)))
2491 {
2492 FileFd Fd(flNotDir(I->Path), FileFd::ReadOnly);
2493 MD5Summation sum;
2494 sum.AddFD(Fd.Fd(), Fd.Size());
2495 Fd.Close();
2496 if((string)sum.Result() == I->MD5Hash)
2497 {
2498 ioprintf(c1out,_("Skipping already downloaded file '%s'\n"),
2499 flNotDir(I->Path).c_str());
2500 continue;
2501 }
2502 }
2503
2504 new pkgAcqFile(&Fetcher,Last->Index().ArchiveURI(I->Path),
2505 I->MD5Hash,I->Size,
2506 Last->Index().SourceInfo(*Last,*I),Src);
2507 }
2508 }
2509
2510 // Display statistics
2511 unsigned long long FetchBytes = Fetcher.FetchNeeded();
2512 unsigned long long FetchPBytes = Fetcher.PartialPresent();
2513 unsigned long long DebBytes = Fetcher.TotalNeeded();
2514
2515 // Check for enough free space
2516 struct statvfs Buf;
2517 string OutputDir = ".";
2518 if (statvfs(OutputDir.c_str(),&Buf) != 0) {
2519 delete[] Dsc;
2520 if (errno == EOVERFLOW)
2521 return _error->WarningE("statvfs",_("Couldn't determine free space in %s"),
2522 OutputDir.c_str());
2523 else
2524 return _error->Errno("statvfs",_("Couldn't determine free space in %s"),
2525 OutputDir.c_str());
2526 } else if (unsigned(Buf.f_bfree) < (FetchBytes - FetchPBytes)/Buf.f_bsize)
2527 {
2528 struct statfs Stat;
2529 if (statfs(OutputDir.c_str(),&Stat) != 0
2530 #if HAVE_STRUCT_STATFS_F_TYPE
2531 || unsigned(Stat.f_type) != RAMFS_MAGIC
2532 #endif
2533 ) {
2534 delete[] Dsc;
2535 return _error->Error(_("You don't have enough free space in %s"),
2536 OutputDir.c_str());
2537 }
2538 }
2539
2540 // Number of bytes
2541 if (DebBytes != FetchBytes)
2542 //TRANSLATOR: The required space between number and unit is already included
2543 // in the replacement strings, so %sB will be correctly translate in e.g. 1,5 MB
2544 ioprintf(c1out,_("Need to get %sB/%sB of source archives.\n"),
2545 SizeToStr(FetchBytes).c_str(),SizeToStr(DebBytes).c_str());
2546 else
2547 //TRANSLATOR: The required space between number and unit is already included
2548 // in the replacement string, so %sB will be correctly translate in e.g. 1,5 MB
2549 ioprintf(c1out,_("Need to get %sB of source archives.\n"),
2550 SizeToStr(DebBytes).c_str());
2551
2552 if (_config->FindB("APT::Get::Simulate",false) == true)
2553 {
2554 for (unsigned I = 0; I != J; I++)
2555 ioprintf(cout,_("Fetch source %s\n"),Dsc[I].Package.c_str());
2556 delete[] Dsc;
2557 return true;
2558 }
2559
2560 // Just print out the uris an exit if the --print-uris flag was used
2561 if (_config->FindB("APT::Get::Print-URIs") == true)
2562 {
2563 pkgAcquire::UriIterator I = Fetcher.UriBegin();
2564 for (; I != Fetcher.UriEnd(); ++I)
2565 cout << '\'' << I->URI << "' " << flNotDir(I->Owner->DestFile) << ' ' <<
2566 I->Owner->FileSize << ' ' << I->Owner->HashSum() << endl;
2567 delete[] Dsc;
2568 return true;
2569 }
2570
2571 // Run it
2572 if (Fetcher.Run() == pkgAcquire::Failed)
2573 {
2574 delete[] Dsc;
2575 return false;
2576 }
2577
2578 // Print error messages
2579 bool Failed = false;
2580 for (pkgAcquire::ItemIterator I = Fetcher.ItemsBegin(); I != Fetcher.ItemsEnd(); ++I)
2581 {
2582 if ((*I)->Status == pkgAcquire::Item::StatDone &&
2583 (*I)->Complete == true)
2584 continue;
2585
2586 fprintf(stderr,_("Failed to fetch %s %s\n"),(*I)->DescURI().c_str(),
2587 (*I)->ErrorText.c_str());
2588 Failed = true;
2589 }
2590 if (Failed == true)
2591 {
2592 delete[] Dsc;
2593 return _error->Error(_("Failed to fetch some archives."));
2594 }
2595
2596 if (_config->FindB("APT::Get::Download-only",false) == true)
2597 {
2598 c1out << _("Download complete and in download only mode") << endl;
2599 delete[] Dsc;
2600 return true;
2601 }
2602
2603 // Unpack the sources
2604 pid_t Process = ExecFork();
2605
2606 if (Process == 0)
2607 {
2608 bool const fixBroken = _config->FindB("APT::Get::Fix-Broken", false);
2609 for (unsigned I = 0; I != J; ++I)
2610 {
2611 string Dir = Dsc[I].Package + '-' + Cache->VS().UpstreamVersion(Dsc[I].Version.c_str());
2612
2613 // Diff only mode only fetches .diff files
2614 if (_config->FindB("APT::Get::Diff-Only",false) == true ||
2615 _config->FindB("APT::Get::Tar-Only",false) == true ||
2616 Dsc[I].Dsc.empty() == true)
2617 continue;
2618
2619 // See if the package is already unpacked
2620 struct stat Stat;
2621 if (fixBroken == false && stat(Dir.c_str(),&Stat) == 0 &&
2622 S_ISDIR(Stat.st_mode) != 0)
2623 {
2624 ioprintf(c0out ,_("Skipping unpack of already unpacked source in %s\n"),
2625 Dir.c_str());
2626 }
2627 else
2628 {
2629 // Call dpkg-source
2630 char S[500];
2631 snprintf(S,sizeof(S),"%s -x %s",
2632 _config->Find("Dir::Bin::dpkg-source","dpkg-source").c_str(),
2633 Dsc[I].Dsc.c_str());
2634 if (system(S) != 0)
2635 {
2636 fprintf(stderr,_("Unpack command '%s' failed.\n"),S);
2637 fprintf(stderr,_("Check if the 'dpkg-dev' package is installed.\n"));
2638 _exit(1);
2639 }
2640 }
2641
2642 // Try to compile it with dpkg-buildpackage
2643 if (_config->FindB("APT::Get::Compile",false) == true)
2644 {
2645 string buildopts = _config->Find("APT::Get::Host-Architecture");
2646 if (buildopts.empty() == false)
2647 buildopts = "-a " + buildopts + " ";
2648 buildopts.append(_config->Find("DPkg::Build-Options","-b -uc"));
2649
2650 // Call dpkg-buildpackage
2651 char S[500];
2652 snprintf(S,sizeof(S),"cd %s && %s %s",
2653 Dir.c_str(),
2654 _config->Find("Dir::Bin::dpkg-buildpackage","dpkg-buildpackage").c_str(),
2655 buildopts.c_str());
2656
2657 if (system(S) != 0)
2658 {
2659 fprintf(stderr,_("Build command '%s' failed.\n"),S);
2660 _exit(1);
2661 }
2662 }
2663 }
2664
2665 _exit(0);
2666 }
2667 delete[] Dsc;
2668
2669 // Wait for the subprocess
2670 int Status = 0;
2671 while (waitpid(Process,&Status,0) != Process)
2672 {
2673 if (errno == EINTR)
2674 continue;
2675 return _error->Errno("waitpid","Couldn't wait for subprocess");
2676 }
2677
2678 if (WIFEXITED(Status) == 0 || WEXITSTATUS(Status) != 0)
2679 return _error->Error(_("Child process failed"));
2680
2681 return true;
2682 }
2683 /*}}}*/
2684 // DoBuildDep - Install/removes packages to satisfy build dependencies /*{{{*/
2685 // ---------------------------------------------------------------------
2686 /* This function will look at the build depends list of the given source
2687 package and install the necessary packages to make it true, or fail. */
2688 bool DoBuildDep(CommandLine &CmdL)
2689 {
2690 CacheFile Cache;
2691
2692 _config->Set("APT::Install-Recommends", false);
2693
2694 if (Cache.Open(true) == false)
2695 return false;
2696
2697 if (CmdL.FileSize() <= 1)
2698 return _error->Error(_("Must specify at least one package to check builddeps for"));
2699
2700 // Read the source list
2701 if (Cache.BuildSourceList() == false)
2702 return false;
2703 pkgSourceList *List = Cache.GetSourceList();
2704
2705 // Create the text record parsers
2706 pkgRecords Recs(Cache);
2707 pkgSrcRecords SrcRecs(*List);
2708 if (_error->PendingError() == true)
2709 return false;
2710
2711 // Create the download object
2712 AcqTextStatus Stat(ScreenWidth,_config->FindI("quiet",0));
2713 pkgAcquire Fetcher;
2714 if (Fetcher.Setup(&Stat) == false)
2715 return false;
2716
2717 bool StripMultiArch;
2718 string hostArch = _config->Find("APT::Get::Host-Architecture");
2719 if (hostArch.empty() == false)
2720 {
2721 std::vector<std::string> archs = APT::Configuration::getArchitectures();
2722 if (std::find(archs.begin(), archs.end(), hostArch) == archs.end())
2723 return _error->Error(_("No architecture information available for %s. See apt.conf(5) APT::Architectures for setup"), hostArch.c_str());
2724 StripMultiArch = false;
2725 }
2726 else
2727 StripMultiArch = true;
2728
2729 unsigned J = 0;
2730 for (const char **I = CmdL.FileList + 1; *I != 0; I++, J++)
2731 {
2732 string Src;
2733 pkgSrcRecords::Parser *Last = FindSrc(*I,Recs,SrcRecs,Src,*Cache);
2734 if (Last == 0)
2735 return _error->Error(_("Unable to find a source package for %s"),Src.c_str());
2736
2737 // Process the build-dependencies
2738 vector<pkgSrcRecords::Parser::BuildDepRec> BuildDeps;
2739 if (Last->BuildDepends(BuildDeps, _config->FindB("APT::Get::Arch-Only", false), StripMultiArch) == false)
2740 return _error->Error(_("Unable to get build-dependency information for %s"),Src.c_str());
2741
2742 // Also ensure that build-essential packages are present
2743 Configuration::Item const *Opts = _config->Tree("APT::Build-Essential");
2744 if (Opts)
2745 Opts = Opts->Child;
2746 for (; Opts; Opts = Opts->Next)
2747 {
2748 if (Opts->Value.empty() == true)
2749 continue;
2750
2751 pkgSrcRecords::Parser::BuildDepRec rec;
2752 rec.Package = Opts->Value;
2753 rec.Type = pkgSrcRecords::Parser::BuildDependIndep;
2754 rec.Op = 0;
2755 BuildDeps.push_back(rec);
2756 }
2757
2758 if (BuildDeps.empty() == true)
2759 {
2760 ioprintf(c1out,_("%s has no build depends.\n"),Src.c_str());
2761 continue;
2762 }
2763
2764 // Install the requested packages
2765 vector <pkgSrcRecords::Parser::BuildDepRec>::iterator D;
2766 pkgProblemResolver Fix(Cache);
2767 bool skipAlternatives = false; // skip remaining alternatives in an or group
2768 for (D = BuildDeps.begin(); D != BuildDeps.end(); ++D)
2769 {
2770 bool hasAlternatives = (((*D).Op & pkgCache::Dep::Or) == pkgCache::Dep::Or);
2771
2772 if (skipAlternatives == true)
2773 {
2774 /*
2775 * if there are alternatives, we've already picked one, so skip
2776 * the rest
2777 *
2778 * TODO: this means that if there's a build-dep on A|B and B is
2779 * installed, we'll still try to install A; more importantly,
2780 * if A is currently broken, we cannot go back and try B. To fix
2781 * this would require we do a Resolve cycle for each package we
2782 * add to the install list. Ugh
2783 */
2784 if (!hasAlternatives)
2785 skipAlternatives = false; // end of or group
2786 continue;
2787 }
2788
2789 if ((*D).Type == pkgSrcRecords::Parser::BuildConflict ||
2790 (*D).Type == pkgSrcRecords::Parser::BuildConflictIndep)
2791 {
2792 pkgCache::GrpIterator Grp = Cache->FindGrp((*D).Package);
2793 // Build-conflicts on unknown packages are silently ignored
2794 if (Grp.end() == true)
2795 continue;
2796
2797 for (pkgCache::PkgIterator Pkg = Grp.PackageList(); Pkg.end() == false; Pkg = Grp.NextPkg(Pkg))
2798 {
2799 pkgCache::VerIterator IV = (*Cache)[Pkg].InstVerIter(*Cache);
2800 /*
2801 * Remove if we have an installed version that satisfies the
2802 * version criteria
2803 */
2804 if (IV.end() == false &&
2805 Cache->VS().CheckDep(IV.VerStr(),(*D).Op,(*D).Version.c_str()) == true)
2806 TryToInstallBuildDep(Pkg,Cache,Fix,true,false);
2807 }
2808 }
2809 else // BuildDep || BuildDepIndep
2810 {
2811 if (_config->FindB("Debug::BuildDeps",false) == true)
2812 cout << "Looking for " << (*D).Package << "...\n";
2813
2814 pkgCache::PkgIterator Pkg;
2815
2816 // Cross-Building?
2817 if (StripMultiArch == false)
2818 {
2819 size_t const colon = D->Package.find(":");
2820 if (colon != string::npos &&
2821 (strcmp(D->Package.c_str() + colon, ":any") == 0 || strcmp(D->Package.c_str() + colon, ":native") == 0))
2822 Pkg = Cache->FindPkg(D->Package.substr(0,colon));
2823 else
2824 Pkg = Cache->FindPkg(D->Package);
2825
2826 // We need to decide if host or build arch, so find a version we can look at
2827 pkgCache::VerIterator Ver;
2828
2829 // a bad version either is invalid or doesn't satify dependency
2830 #define BADVER(Ver) Ver.end() == true || \
2831 (Ver.end() == false && D->Version.empty() == false && \
2832 Cache->VS().CheckDep(Ver.VerStr(),D->Op,D->Version.c_str()) == false)
2833
2834 if (Pkg.end() == false)
2835 {
2836 Ver = (*Cache)[Pkg].InstVerIter(*Cache);
2837 if (BADVER(Ver))
2838 Ver = (*Cache)[Pkg].CandidateVerIter(*Cache);
2839 }
2840 if (BADVER(Ver))
2841 {
2842 pkgCache::PkgIterator HostPkg = Cache->FindPkg(D->Package, hostArch);
2843 if (HostPkg.end() == false)
2844 {
2845 Ver = (*Cache)[HostPkg].InstVerIter(*Cache);
2846 if (BADVER(Ver))
2847 Ver = (*Cache)[HostPkg].CandidateVerIter(*Cache);
2848 }
2849 }
2850 if ((BADVER(Ver)) == false)
2851 {
2852 string forbidden;
2853 if (Ver->MultiArch == pkgCache::Version::None || Ver->MultiArch == pkgCache::Version::All);
2854 else if (Ver->MultiArch == pkgCache::Version::Same)
2855 {
2856 if (colon != string::npos)
2857 Pkg = Ver.ParentPkg().Group().FindPkg(hostArch);
2858 else if (strcmp(D->Package.c_str() + colon, ":any") == 0)
2859 forbidden = "Multi-Arch: same";
2860 // :native gets the buildArch
2861 }
2862 else if (Ver->MultiArch == pkgCache::Version::Foreign || Ver->MultiArch == pkgCache::Version::AllForeign)
2863 {
2864 if (colon != string::npos)
2865 forbidden = "Multi-Arch: foreign";
2866 }
2867 else if (Ver->MultiArch == pkgCache::Version::Allowed || Ver->MultiArch == pkgCache::Version::AllAllowed)
2868 {
2869 if (colon == string::npos)
2870 Pkg = Ver.ParentPkg().Group().FindPkg(hostArch);
2871 else if (strcmp(D->Package.c_str() + colon, ":any") == 0)
2872 {
2873 // prefer any installed over preferred non-installed architectures
2874 pkgCache::GrpIterator Grp = Ver.ParentPkg().Group();
2875 // we don't check for version here as we are better of with upgrading than remove and install
2876 for (Pkg = Grp.PackageList(); Pkg.end() == false; Pkg = Grp.NextPkg(Pkg))
2877 if (Pkg.CurrentVer().end() == false)
2878 break;
2879 if (Pkg.end() == true)
2880 Pkg = Grp.FindPreferredPkg(true);
2881 }
2882 // native gets buildArch
2883 }
2884 if (forbidden.empty() == false)
2885 {
2886 if (_config->FindB("Debug::BuildDeps",false) == true)
2887 cout << " :any is not allowed from M-A: same package " << (*D).Package << endl;
2888 if (hasAlternatives)
2889 continue;
2890 return _error->Error(_("%s dependency for %s can't be satisfied "
2891 "because %s is not allowed on '%s' packages"),
2892 Last->BuildDepType(D->Type), Src.c_str(),
2893 D->Package.c_str(), "Multi-Arch: same");
2894 }
2895 }
2896 else if (_config->FindB("Debug::BuildDeps",false) == true)
2897 cout << " No multiarch info as we have no satisfying installed nor candidate for " << D->Package << " on build or host arch" << endl;
2898 #undef BADVER
2899 }
2900 else
2901 Pkg = Cache->FindPkg(D->Package);
2902
2903 if (Pkg.end() == true)
2904 {
2905 if (_config->FindB("Debug::BuildDeps",false) == true)
2906 cout << " (not found)" << (*D).Package << endl;
2907
2908 if (hasAlternatives)
2909 continue;
2910
2911 return _error->Error(_("%s dependency for %s cannot be satisfied "
2912 "because the package %s cannot be found"),
2913 Last->BuildDepType((*D).Type),Src.c_str(),
2914 (*D).Package.c_str());
2915 }
2916
2917 pkgCache::VerIterator IV = (*Cache)[Pkg].InstVerIter(*Cache);
2918 if (IV.end() == false)
2919 {
2920 if (_config->FindB("Debug::BuildDeps",false) == true)
2921 cout << " Is installed\n";
2922
2923 if (D->Version.empty() == true ||
2924 Cache->VS().CheckDep(IV.VerStr(),(*D).Op,(*D).Version.c_str()) == true)
2925 {
2926 skipAlternatives = hasAlternatives;
2927 continue;
2928 }
2929
2930 if (_config->FindB("Debug::BuildDeps",false) == true)
2931 cout << " ...but the installed version doesn't meet the version requirement\n";
2932
2933 if (((*D).Op & pkgCache::Dep::LessEq) == pkgCache::Dep::LessEq)
2934 return _error->Error(_("Failed to satisfy %s dependency for %s: Installed package %s is too new"),
2935 Last->BuildDepType((*D).Type), Src.c_str(), Pkg.FullName(true).c_str());
2936 }
2937
2938 // Only consider virtual packages if there is no versioned dependency
2939 if ((*D).Version.empty() == true)
2940 {
2941 /*
2942 * If this is a virtual package, we need to check the list of
2943 * packages that provide it and see if any of those are
2944 * installed
2945 */
2946 pkgCache::PrvIterator Prv = Pkg.ProvidesList();
2947 for (; Prv.end() != true; ++Prv)
2948 {
2949 if (_config->FindB("Debug::BuildDeps",false) == true)
2950 cout << " Checking provider " << Prv.OwnerPkg().FullName() << endl;
2951
2952 if ((*Cache)[Prv.OwnerPkg()].InstVerIter(*Cache).end() == false)
2953 break;
2954 }
2955
2956 if (Prv.end() == false)
2957 {
2958 if (_config->FindB("Debug::BuildDeps",false) == true)
2959 cout << " Is provided by installed package " << Prv.OwnerPkg().FullName() << endl;
2960 skipAlternatives = hasAlternatives;
2961 continue;
2962 }
2963 }
2964 else // versioned dependency
2965 {
2966 pkgCache::VerIterator CV = (*Cache)[Pkg].CandidateVerIter(*Cache);
2967 if (CV.end() == true ||
2968 Cache->VS().CheckDep(CV.VerStr(),(*D).Op,(*D).Version.c_str()) == false)
2969 {
2970 if (hasAlternatives)
2971 continue;
2972 else if (CV.end() == false)
2973 return _error->Error(_("%s dependency for %s cannot be satisfied "
2974 "because candidate version of package %s "
2975 "can't satisfy version requirements"),
2976 Last->BuildDepType(D->Type), Src.c_str(),
2977 D->Package.c_str());
2978 else
2979 return _error->Error(_("%s dependency for %s cannot be satisfied "
2980 "because package %s has no candidate version"),
2981 Last->BuildDepType(D->Type), Src.c_str(),
2982 D->Package.c_str());
2983 }
2984 }
2985
2986 if (TryToInstallBuildDep(Pkg,Cache,Fix,false,false) == true)
2987 {
2988 // We successfully installed something; skip remaining alternatives
2989 skipAlternatives = hasAlternatives;
2990 if(_config->FindB("APT::Get::Build-Dep-Automatic", false) == true)
2991 Cache->MarkAuto(Pkg, true);
2992 continue;
2993 }
2994 else if (hasAlternatives)
2995 {
2996 if (_config->FindB("Debug::BuildDeps",false) == true)
2997 cout << " Unsatisfiable, trying alternatives\n";
2998 continue;
2999 }
3000 else
3001 {
3002 return _error->Error(_("Failed to satisfy %s dependency for %s: %s"),
3003 Last->BuildDepType((*D).Type),
3004 Src.c_str(),
3005 (*D).Package.c_str());
3006 }
3007 }
3008 }
3009
3010 Fix.InstallProtect();
3011 if (Fix.Resolve(true) == false)
3012 _error->Discard();
3013
3014 // Now we check the state of the packages,
3015 if (Cache->BrokenCount() != 0)
3016 {
3017 ShowBroken(cout, Cache, false);
3018 return _error->Error(_("Build-dependencies for %s could not be satisfied."),*I);
3019 }
3020 }
3021
3022 if (InstallPackages(Cache, false, true) == false)
3023 return _error->Error(_("Failed to process build dependencies"));
3024 return true;
3025 }
3026 /*}}}*/
3027 // GetChangelogPath - return a path pointing to a changelog file or dir /*{{{*/
3028 // ---------------------------------------------------------------------
3029 /* This returns a "path" string for the changelog url construction.
3030 * Please note that its not complete, it either needs a "/changelog"
3031 * appended (for the packages.debian.org/changelogs site) or a
3032 * ".changelog" (for third party sites that store the changelog in the
3033 * pool/ next to the deb itself)
3034 * Example return: "pool/main/a/apt/apt_0.8.8ubuntu3"
3035 */
3036 string GetChangelogPath(CacheFile &Cache,
3037 pkgCache::PkgIterator Pkg,
3038 pkgCache::VerIterator Ver)
3039 {
3040 string path;
3041
3042 pkgRecords Recs(Cache);
3043 pkgRecords::Parser &rec=Recs.Lookup(Ver.FileList());
3044 string srcpkg = rec.SourcePkg().empty() ? Pkg.Name() : rec.SourcePkg();
3045 string ver = Ver.VerStr();
3046 // if there is a source version it always wins
3047 if (rec.SourceVer() != "")
3048 ver = rec.SourceVer();
3049 path = flNotFile(rec.FileName());
3050 path += srcpkg + "_" + StripEpoch(ver);
3051 return path;
3052 }
3053 /*}}}*/
3054 // GuessThirdPartyChangelogUri - return url /*{{{*/
3055 // ---------------------------------------------------------------------
3056 /* Contruct a changelog file path for third party sites that do not use
3057 * packages.debian.org/changelogs
3058 * This simply uses the ArchiveURI() of the source pkg and looks for
3059 * a .changelog file there, Example for "mediabuntu":
3060 * apt-get changelog mplayer-doc:
3061 * http://packages.medibuntu.org/pool/non-free/m/mplayer/mplayer_1.0~rc4~try1.dsfg1-1ubuntu1+medibuntu1.changelog
3062 */
3063 bool GuessThirdPartyChangelogUri(CacheFile &Cache,
3064 pkgCache::PkgIterator Pkg,
3065 pkgCache::VerIterator Ver,
3066 string &out_uri)
3067 {
3068 // get the binary deb server path
3069 pkgCache::VerFileIterator Vf = Ver.FileList();
3070 if (Vf.end() == true)
3071 return false;
3072 pkgCache::PkgFileIterator F = Vf.File();
3073 pkgIndexFile *index;
3074 pkgSourceList *SrcList = Cache.GetSourceList();
3075 if(SrcList->FindIndex(F, index) == false)
3076 return false;
3077
3078 // get archive uri for the binary deb
3079 string path_without_dot_changelog = GetChangelogPath(Cache, Pkg, Ver);
3080 out_uri = index->ArchiveURI(path_without_dot_changelog + ".changelog");
3081
3082 // now strip away the filename and add srcpkg_srcver.changelog
3083 return true;
3084 }
3085 /*}}}*/
3086 // DownloadChangelog - Download the changelog /*{{{*/
3087 // ---------------------------------------------------------------------
3088 bool DownloadChangelog(CacheFile &CacheFile, pkgAcquire &Fetcher,
3089 pkgCache::VerIterator Ver, string targetfile)
3090 /* Download a changelog file for the given package version to
3091 * targetfile. This will first try the server from Apt::Changelogs::Server
3092 * (http://packages.debian.org/changelogs by default) and if that gives
3093 * a 404 tries to get it from the archive directly (see
3094 * GuessThirdPartyChangelogUri for details how)
3095 */
3096 {
3097 string path;
3098 string descr;
3099 string server;
3100 string changelog_uri;
3101
3102 // data structures we need
3103 pkgCache::PkgIterator Pkg = Ver.ParentPkg();
3104
3105 // make the server root configurable
3106 server = _config->Find("Apt::Changelogs::Server",
3107 "http://packages.debian.org/changelogs");
3108 path = GetChangelogPath(CacheFile, Pkg, Ver);
3109 strprintf(changelog_uri, "%s/%s/changelog", server.c_str(), path.c_str());
3110 if (_config->FindB("APT::Get::Print-URIs", false) == true)
3111 {
3112 std::cout << '\'' << changelog_uri << '\'' << std::endl;
3113 return true;
3114 }
3115
3116 strprintf(descr, _("Changelog for %s (%s)"), Pkg.Name(), changelog_uri.c_str());
3117 // queue it
3118 new pkgAcqFile(&Fetcher, changelog_uri, "", 0, descr, Pkg.Name(), "ignored", targetfile);
3119
3120 // try downloading it, if that fails, try third-party-changelogs location
3121 // FIXME: Fetcher.Run() is "Continue" even if I get a 404?!?
3122 Fetcher.Run();
3123 if (!FileExists(targetfile))
3124 {
3125 string third_party_uri;
3126 if (GuessThirdPartyChangelogUri(CacheFile, Pkg, Ver, third_party_uri))
3127 {
3128 strprintf(descr, _("Changelog for %s (%s)"), Pkg.Name(), third_party_uri.c_str());
3129 new pkgAcqFile(&Fetcher, third_party_uri, "", 0, descr, Pkg.Name(), "ignored", targetfile);
3130 Fetcher.Run();
3131 }
3132 }
3133
3134 if (FileExists(targetfile))
3135 return true;
3136
3137 // error
3138 return _error->Error("changelog download failed");
3139 }
3140 /*}}}*/
3141 // DisplayFileInPager - Display File with pager /*{{{*/
3142 void DisplayFileInPager(string filename)
3143 {
3144 pid_t Process = ExecFork();
3145 if (Process == 0)
3146 {
3147 const char *Args[3];
3148 Args[0] = "/usr/bin/sensible-pager";
3149 Args[1] = filename.c_str();
3150 Args[2] = 0;
3151 execvp(Args[0],(char **)Args);
3152 exit(100);
3153 }
3154
3155 // Wait for the subprocess
3156 ExecWait(Process, "sensible-pager", false);
3157 }
3158 /*}}}*/
3159 // DoChangelog - Get changelog from the command line /*{{{*/
3160 // ---------------------------------------------------------------------
3161 bool DoChangelog(CommandLine &CmdL)
3162 {
3163 CacheFile Cache;
3164 if (Cache.ReadOnlyOpen() == false)
3165 return false;
3166
3167 APT::CacheSetHelper helper(c0out);
3168 APT::VersionSet verset = APT::VersionSet::FromCommandLine(Cache,
3169 CmdL.FileList + 1, APT::VersionSet::CANDIDATE, helper);
3170 if (verset.empty() == true)
3171 return false;
3172 pkgAcquire Fetcher;
3173
3174 if (_config->FindB("APT::Get::Print-URIs", false) == true)
3175 for (APT::VersionSet::const_iterator Ver = verset.begin();
3176 Ver != verset.end(); ++Ver)
3177 return DownloadChangelog(Cache, Fetcher, Ver, "");
3178
3179 AcqTextStatus Stat(ScreenWidth, _config->FindI("quiet",0));
3180 Fetcher.Setup(&Stat);
3181
3182 bool const downOnly = _config->FindB("APT::Get::Download-Only", false);
3183
3184 char tmpname[100];
3185 char* tmpdir = NULL;
3186 if (downOnly == false)
3187 {
3188 const char* const tmpDir = getenv("TMPDIR");
3189 if (tmpDir != NULL && *tmpDir != '\0')
3190 snprintf(tmpname, sizeof(tmpname), "%s/apt-changelog-XXXXXX", tmpDir);
3191 else
3192 strncpy(tmpname, "/tmp/apt-changelog-XXXXXX", sizeof(tmpname));
3193 tmpdir = mkdtemp(tmpname);
3194 if (tmpdir == NULL)
3195 return _error->Errno("mkdtemp", "mkdtemp failed");
3196 }
3197
3198 for (APT::VersionSet::const_iterator Ver = verset.begin();
3199 Ver != verset.end();
3200 ++Ver)
3201 {
3202 string changelogfile;
3203 if (downOnly == false)
3204 changelogfile.append(tmpname).append("changelog");
3205 else
3206 changelogfile.append(Ver.ParentPkg().Name()).append(".changelog");
3207 if (DownloadChangelog(Cache, Fetcher, Ver, changelogfile) && downOnly == false)
3208 {
3209 DisplayFileInPager(changelogfile);
3210 // cleanup temp file
3211 unlink(changelogfile.c_str());
3212 }
3213 }
3214 // clenaup tmp dir
3215 if (tmpdir != NULL)
3216 rmdir(tmpdir);
3217 return true;
3218 }
3219 /*}}}*/
3220 // DoMoo - Never Ask, Never Tell /*{{{*/
3221 // ---------------------------------------------------------------------
3222 /* */
3223 bool DoMoo(CommandLine &CmdL)
3224 {
3225 cout <<
3226 " (__) \n"
3227 " (oo) \n"
3228 " /------\\/ \n"
3229 " / | || \n"
3230 " * /\\---/\\ \n"
3231 " ~~ ~~ \n"
3232 "....\"Have you mooed today?\"...\n";
3233
3234 return true;
3235 }
3236 /*}}}*/
3237 // ShowHelp - Show a help screen /*{{{*/
3238 // ---------------------------------------------------------------------
3239 /* */
3240 bool ShowHelp(CommandLine &CmdL)
3241 {
3242 ioprintf(cout,_("%s %s for %s compiled on %s %s\n"),PACKAGE,VERSION,
3243 COMMON_ARCH,__DATE__,__TIME__);
3244
3245 if (_config->FindB("version") == true)
3246 {
3247 cout << _("Supported modules:") << endl;
3248
3249 for (unsigned I = 0; I != pkgVersioningSystem::GlobalListLen; I++)
3250 {
3251 pkgVersioningSystem *VS = pkgVersioningSystem::GlobalList[I];
3252 if (_system != 0 && _system->VS == VS)
3253 cout << '*';
3254 else
3255 cout << ' ';
3256 cout << "Ver: " << VS->Label << endl;
3257
3258 /* Print out all the packaging systems that will work with
3259 this VS */
3260 for (unsigned J = 0; J != pkgSystem::GlobalListLen; J++)
3261 {
3262 pkgSystem *Sys = pkgSystem::GlobalList[J];
3263 if (_system == Sys)
3264 cout << '*';
3265 else
3266 cout << ' ';
3267 if (Sys->VS->TestCompatibility(*VS) == true)
3268 cout << "Pkg: " << Sys->Label << " (Priority " << Sys->Score(*_config) << ")" << endl;
3269 }
3270 }
3271
3272 for (unsigned I = 0; I != pkgSourceList::Type::GlobalListLen; I++)
3273 {
3274 pkgSourceList::Type *Type = pkgSourceList::Type::GlobalList[I];
3275 cout << " S.L: '" << Type->Name << "' " << Type->Label << endl;
3276 }
3277
3278 for (unsigned I = 0; I != pkgIndexFile::Type::GlobalListLen; I++)
3279 {
3280 pkgIndexFile::Type *Type = pkgIndexFile::Type::GlobalList[I];
3281 cout << " Idx: " << Type->Label << endl;
3282 }
3283
3284 return true;
3285 }
3286
3287 cout <<
3288 _("Usage: apt-get [options] command\n"
3289 " apt-get [options] install|remove pkg1 [pkg2 ...]\n"
3290 " apt-get [options] source pkg1 [pkg2 ...]\n"
3291 "\n"
3292 "apt-get is a simple command line interface for downloading and\n"
3293 "installing packages. The most frequently used commands are update\n"
3294 "and install.\n"
3295 "\n"
3296 "Commands:\n"
3297 " update - Retrieve new lists of packages\n"
3298 " upgrade - Perform an upgrade\n"
3299 " install - Install new packages (pkg is libc6 not libc6.deb)\n"
3300 " remove - Remove packages\n"
3301 " autoremove - Remove automatically all unused packages\n"
3302 " purge - Remove packages and config files\n"
3303 " source - Download source archives\n"
3304 " build-dep - Configure build-dependencies for source packages\n"
3305 " dist-upgrade - Distribution upgrade, see apt-get(8)\n"
3306 " dselect-upgrade - Follow dselect selections\n"
3307 " clean - Erase downloaded archive files\n"
3308 " autoclean - Erase old downloaded archive files\n"
3309 " check - Verify that there are no broken dependencies\n"
3310 " changelog - Download and display the changelog for the given package\n"
3311 " download - Download the binary package into the current directory\n"
3312 "\n"
3313 "Options:\n"
3314 " -h This help text.\n"
3315 " -q Loggable output - no progress indicator\n"
3316 " -qq No output except for errors\n"
3317 " -d Download only - do NOT install or unpack archives\n"
3318 " -s No-act. Perform ordering simulation\n"
3319 " -y Assume Yes to all queries and do not prompt\n"
3320 " -f Attempt to correct a system with broken dependencies in place\n"
3321 " -m Attempt to continue if archives are unlocatable\n"
3322 " -u Show a list of upgraded packages as well\n"
3323 " -b Build the source package after fetching it\n"
3324 " -V Show verbose version numbers\n"
3325 " -c=? Read this configuration file\n"
3326 " -o=? Set an arbitrary configuration option, eg -o dir::cache=/tmp\n"
3327 "See the apt-get(8), sources.list(5) and apt.conf(5) manual\n"
3328 "pages for more information and options.\n"
3329 " This APT has Super Cow Powers.\n");
3330 return true;
3331 }
3332 /*}}}*/
3333 // SigWinch - Window size change signal handler /*{{{*/
3334 // ---------------------------------------------------------------------
3335 /* */
3336 void SigWinch(int)
3337 {
3338 // Riped from GNU ls
3339 #ifdef TIOCGWINSZ
3340 struct winsize ws;
3341
3342 if (ioctl(1, TIOCGWINSZ, &ws) != -1 && ws.ws_col >= 5)
3343 ScreenWidth = ws.ws_col - 1;
3344 #endif
3345 }
3346 /*}}}*/
3347 int main(int argc,const char *argv[]) /*{{{*/
3348 {
3349 CommandLine::Args Args[] = {
3350 {'h',"help","help",0},
3351 {'v',"version","version",0},
3352 {'V',"verbose-versions","APT::Get::Show-Versions",0},
3353 {'q',"quiet","quiet",CommandLine::IntLevel},
3354 {'q',"silent","quiet",CommandLine::IntLevel},
3355 {'d',"download-only","APT::Get::Download-Only",0},
3356 {'b',"compile","APT::Get::Compile",0},
3357 {'b',"build","APT::Get::Compile",0},
3358 {'s',"simulate","APT::Get::Simulate",0},
3359 {'s',"just-print","APT::Get::Simulate",0},
3360 {'s',"recon","APT::Get::Simulate",0},
3361 {'s',"dry-run","APT::Get::Simulate",0},
3362 {'s',"no-act","APT::Get::Simulate",0},
3363 {'y',"yes","APT::Get::Assume-Yes",0},
3364 {'y',"assume-yes","APT::Get::Assume-Yes",0},
3365 {0,"assume-no","APT::Get::Assume-No",0},
3366 {'f',"fix-broken","APT::Get::Fix-Broken",0},
3367 {'u',"show-upgraded","APT::Get::Show-Upgraded",0},
3368 {'m',"ignore-missing","APT::Get::Fix-Missing",0},
3369 {'t',"target-release","APT::Default-Release",CommandLine::HasArg},
3370 {'t',"default-release","APT::Default-Release",CommandLine::HasArg},
3371 {'a',"host-architecture","APT::Get::Host-Architecture",CommandLine::HasArg},
3372 {0,"download","APT::Get::Download",0},
3373 {0,"fix-missing","APT::Get::Fix-Missing",0},
3374 {0,"ignore-hold","APT::Ignore-Hold",0},
3375 {0,"upgrade","APT::Get::upgrade",0},
3376 {0,"only-upgrade","APT::Get::Only-Upgrade",0},
3377 {0,"force-yes","APT::Get::force-yes",0},
3378 {0,"print-uris","APT::Get::Print-URIs",0},
3379 {0,"diff-only","APT::Get::Diff-Only",0},
3380 {0,"debian-only","APT::Get::Diff-Only",0},
3381 {0,"tar-only","APT::Get::Tar-Only",0},
3382 {0,"dsc-only","APT::Get::Dsc-Only",0},
3383 {0,"purge","APT::Get::Purge",0},
3384 {0,"list-cleanup","APT::Get::List-Cleanup",0},
3385 {0,"reinstall","APT::Get::ReInstall",0},
3386 {0,"trivial-only","APT::Get::Trivial-Only",0},
3387 {0,"remove","APT::Get::Remove",0},
3388 {0,"only-source","APT::Get::Only-Source",0},
3389 {0,"arch-only","APT::Get::Arch-Only",0},
3390 {0,"auto-remove","APT::Get::AutomaticRemove",0},
3391 {0,"allow-unauthenticated","APT::Get::AllowUnauthenticated",0},
3392 {0,"install-recommends","APT::Install-Recommends",CommandLine::Boolean},
3393 {0,"install-suggests","APT::Install-Suggests",CommandLine::Boolean},
3394 {0,"fix-policy","APT::Get::Fix-Policy-Broken",0},
3395 {0,"solver","APT::Solver",CommandLine::HasArg},
3396 {'c',"config-file",0,CommandLine::ConfigFile},
3397 {'o',"option",0,CommandLine::ArbItem},
3398 {0,0,0,0}};
3399 CommandLine::Dispatch Cmds[] = {{"update",&DoUpdate},
3400 {"upgrade",&DoUpgrade},
3401 {"install",&DoInstall},
3402 {"remove",&DoInstall},
3403 {"purge",&DoInstall},
3404 {"autoremove",&DoInstall},
3405 {"markauto",&DoMarkAuto},
3406 {"unmarkauto",&DoMarkAuto},
3407 {"dist-upgrade",&DoDistUpgrade},
3408 {"dselect-upgrade",&DoDSelectUpgrade},
3409 {"build-dep",&DoBuildDep},
3410 {"clean",&DoClean},
3411 {"autoclean",&DoAutoClean},
3412 {"check",&DoCheck},
3413 {"source",&DoSource},
3414 {"download",&DoDownload},
3415 {"changelog",&DoChangelog},
3416 {"moo",&DoMoo},
3417 {"help",&ShowHelp},
3418 {0,0}};
3419
3420 // Set up gettext support
3421 setlocale(LC_ALL,"");
3422 textdomain(PACKAGE);
3423
3424 // Parse the command line and initialize the package library
3425 CommandLine CmdL(Args,_config);
3426 if (pkgInitConfig(*_config) == false ||
3427 CmdL.Parse(argc,argv) == false ||
3428 pkgInitSystem(*_config,_system) == false)
3429 {
3430 if (_config->FindB("version") == true)
3431 ShowHelp(CmdL);
3432
3433 _error->DumpErrors();
3434 return 100;
3435 }
3436
3437 // See if the help should be shown
3438 if (_config->FindB("help") == true ||
3439 _config->FindB("version") == true ||
3440 CmdL.FileSize() == 0)
3441 {
3442 ShowHelp(CmdL);
3443 return 0;
3444 }
3445
3446 // simulate user-friendly if apt-get has no root privileges
3447 if (getuid() != 0 && _config->FindB("APT::Get::Simulate") == true &&
3448 (CmdL.FileSize() == 0 ||
3449 (strcmp(CmdL.FileList[0], "source") != 0 && strcmp(CmdL.FileList[0], "download") != 0 &&
3450 strcmp(CmdL.FileList[0], "changelog") != 0)))
3451 {
3452 if (_config->FindB("APT::Get::Show-User-Simulation-Note",true) == true)
3453 cout << _("NOTE: This is only a simulation!\n"
3454 " apt-get needs root privileges for real execution.\n"
3455 " Keep also in mind that locking is deactivated,\n"
3456 " so don't depend on the relevance to the real current situation!"
3457 ) << std::endl;
3458 _config->Set("Debug::NoLocking",true);
3459 }
3460
3461 // Deal with stdout not being a tty
3462 if (!isatty(STDOUT_FILENO) && _config->FindI("quiet", -1) == -1)
3463 _config->Set("quiet","1");
3464
3465 // Setup the output streams
3466 c0out.rdbuf(cout.rdbuf());
3467 c1out.rdbuf(cout.rdbuf());
3468 c2out.rdbuf(cout.rdbuf());
3469 if (_config->FindI("quiet",0) > 0)
3470 c0out.rdbuf(devnull.rdbuf());
3471 if (_config->FindI("quiet",0) > 1)
3472 c1out.rdbuf(devnull.rdbuf());
3473
3474 // Setup the signals
3475 signal(SIGPIPE,SIG_IGN);
3476 signal(SIGWINCH,SigWinch);
3477 SigWinch(0);
3478
3479 // Match the operation
3480 CmdL.DispatchArg(Cmds);
3481
3482 // Print any errors or warnings found during parsing
3483 bool const Errors = _error->PendingError();
3484 if (_config->FindI("quiet",0) > 0)
3485 _error->DumpErrors();
3486 else
3487 _error->DumpErrors(GlobalError::DEBUG);
3488 return Errors == true ? 100 : 0;
3489 }
3490 /*}}}*/