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