]> git.saurik.com Git - apt.git/blob - cmdline/apt-get.cc
Merge remote-tracking branch 'upstream/debian/sid' into bugfix/coverity
[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 CacheFile Cache;
1878 if (Cache.OpenForInstall() == false || Cache.CheckDeps() == false)
1879 return false;
1880
1881 // Do the upgrade
1882 if (pkgAllUpgrade(Cache) == false)
1883 {
1884 ShowBroken(c1out,Cache,false);
1885 return _error->Error(_("Internal error, AllUpgrade broke stuff"));
1886 }
1887
1888 return InstallPackages(Cache,true);
1889 }
1890 /*}}}*/
1891 // DoInstall - Install packages from the command line /*{{{*/
1892 // ---------------------------------------------------------------------
1893 /* Install named packages */
1894 bool DoInstall(CommandLine &CmdL)
1895 {
1896 CacheFile Cache;
1897 if (Cache.OpenForInstall() == false ||
1898 Cache.CheckDeps(CmdL.FileSize() != 1) == false)
1899 return false;
1900
1901 // Enter the special broken fixing mode if the user specified arguments
1902 bool BrokenFix = false;
1903 if (Cache->BrokenCount() != 0)
1904 BrokenFix = true;
1905
1906 pkgProblemResolver* Fix = NULL;
1907 if (_config->FindB("APT::Get::CallResolver", true) == true)
1908 Fix = new pkgProblemResolver(Cache);
1909
1910 static const unsigned short MOD_REMOVE = 1;
1911 static const unsigned short MOD_INSTALL = 2;
1912
1913 unsigned short fallback = MOD_INSTALL;
1914 if (strcasecmp(CmdL.FileList[0],"remove") == 0)
1915 fallback = MOD_REMOVE;
1916 else if (strcasecmp(CmdL.FileList[0], "purge") == 0)
1917 {
1918 _config->Set("APT::Get::Purge", true);
1919 fallback = MOD_REMOVE;
1920 }
1921 else if (strcasecmp(CmdL.FileList[0], "autoremove") == 0)
1922 {
1923 _config->Set("APT::Get::AutomaticRemove", "true");
1924 fallback = MOD_REMOVE;
1925 }
1926
1927 std::list<APT::VersionSet::Modifier> mods;
1928 mods.push_back(APT::VersionSet::Modifier(MOD_INSTALL, "+",
1929 APT::VersionSet::Modifier::POSTFIX, APT::VersionSet::CANDIDATE));
1930 mods.push_back(APT::VersionSet::Modifier(MOD_REMOVE, "-",
1931 APT::VersionSet::Modifier::POSTFIX, APT::VersionSet::NEWEST));
1932 CacheSetHelperAPTGet helper(c0out);
1933 std::map<unsigned short, APT::VersionSet> verset = APT::VersionSet::GroupedFromCommandLine(Cache,
1934 CmdL.FileList + 1, mods, fallback, helper);
1935
1936 if (_error->PendingError() == true)
1937 {
1938 helper.showVirtualPackageErrors(Cache);
1939 if (Fix != NULL)
1940 delete Fix;
1941 return false;
1942 }
1943
1944
1945 TryToInstall InstallAction(Cache, Fix, BrokenFix);
1946 TryToRemove RemoveAction(Cache, Fix);
1947
1948 // new scope for the ActionGroup
1949 {
1950 pkgDepCache::ActionGroup group(Cache);
1951 unsigned short const order[] = { MOD_REMOVE, MOD_INSTALL, 0 };
1952
1953 for (unsigned short i = 0; order[i] != 0; ++i)
1954 {
1955 if (order[i] == MOD_INSTALL)
1956 InstallAction = std::for_each(verset[MOD_INSTALL].begin(), verset[MOD_INSTALL].end(), InstallAction);
1957 else if (order[i] == MOD_REMOVE)
1958 RemoveAction = std::for_each(verset[MOD_REMOVE].begin(), verset[MOD_REMOVE].end(), RemoveAction);
1959 }
1960
1961 if (Fix != NULL && _config->FindB("APT::Get::AutoSolving", true) == true)
1962 {
1963 for (unsigned short i = 0; order[i] != 0; ++i)
1964 {
1965 if (order[i] != MOD_INSTALL)
1966 continue;
1967 InstallAction.propergateReleaseCandiateSwitching(helper.selectedByRelease, c0out);
1968 InstallAction.doAutoInstall();
1969 }
1970 }
1971
1972 if (_error->PendingError() == true)
1973 {
1974 if (Fix != NULL)
1975 delete Fix;
1976 return false;
1977 }
1978
1979 /* If we are in the Broken fixing mode we do not attempt to fix the
1980 problems. This is if the user invoked install without -f and gave
1981 packages */
1982 if (BrokenFix == true && Cache->BrokenCount() != 0)
1983 {
1984 c1out << _("You might want to run 'apt-get -f install' to correct these:") << endl;
1985 ShowBroken(c1out,Cache,false);
1986 if (Fix != NULL)
1987 delete Fix;
1988 return _error->Error(_("Unmet dependencies. Try 'apt-get -f install' with no packages (or specify a solution)."));
1989 }
1990
1991 if (Fix != NULL)
1992 {
1993 // Call the scored problem resolver
1994 Fix->Resolve(true);
1995 delete Fix;
1996 }
1997
1998 // Now we check the state of the packages,
1999 if (Cache->BrokenCount() != 0)
2000 {
2001 c1out <<
2002 _("Some packages could not be installed. This may mean that you have\n"
2003 "requested an impossible situation or if you are using the unstable\n"
2004 "distribution that some required packages have not yet been created\n"
2005 "or been moved out of Incoming.") << endl;
2006 /*
2007 if (Packages == 1)
2008 {
2009 c1out << endl;
2010 c1out <<
2011 _("Since you only requested a single operation it is extremely likely that\n"
2012 "the package is simply not installable and a bug report against\n"
2013 "that package should be filed.") << endl;
2014 }
2015 */
2016
2017 c1out << _("The following information may help to resolve the situation:") << endl;
2018 c1out << endl;
2019 ShowBroken(c1out,Cache,false);
2020 if (_error->PendingError() == true)
2021 return false;
2022 else
2023 return _error->Error(_("Broken packages"));
2024 }
2025 }
2026 if (!DoAutomaticRemove(Cache))
2027 return false;
2028
2029 /* Print out a list of packages that are going to be installed extra
2030 to what the user asked */
2031 if (Cache->InstCount() != verset[MOD_INSTALL].size())
2032 {
2033 string List;
2034 string VersionsList;
2035 for (unsigned J = 0; J < Cache->Head().PackageCount; J++)
2036 {
2037 pkgCache::PkgIterator I(Cache,Cache.List[J]);
2038 if ((*Cache)[I].Install() == false)
2039 continue;
2040 pkgCache::VerIterator Cand = Cache[I].CandidateVerIter(Cache);
2041
2042 if (verset[MOD_INSTALL].find(Cand) != verset[MOD_INSTALL].end())
2043 continue;
2044
2045 List += I.FullName(true) + " ";
2046 VersionsList += string(Cache[I].CandVersion) + "\n";
2047 }
2048
2049 ShowList(c1out,_("The following extra packages will be installed:"),List,VersionsList);
2050 }
2051
2052 /* Print out a list of suggested and recommended packages */
2053 {
2054 string SuggestsList, RecommendsList;
2055 string SuggestsVersions, RecommendsVersions;
2056 for (unsigned J = 0; J < Cache->Head().PackageCount; J++)
2057 {
2058 pkgCache::PkgIterator Pkg(Cache,Cache.List[J]);
2059
2060 /* Just look at the ones we want to install */
2061 if ((*Cache)[Pkg].Install() == false)
2062 continue;
2063
2064 // get the recommends/suggests for the candidate ver
2065 pkgCache::VerIterator CV = (*Cache)[Pkg].CandidateVerIter(*Cache);
2066 for (pkgCache::DepIterator D = CV.DependsList(); D.end() == false; )
2067 {
2068 pkgCache::DepIterator Start;
2069 pkgCache::DepIterator End;
2070 D.GlobOr(Start,End); // advances D
2071
2072 // FIXME: we really should display a or-group as a or-group to the user
2073 // the problem is that ShowList is incapable of doing this
2074 string RecommendsOrList,RecommendsOrVersions;
2075 string SuggestsOrList,SuggestsOrVersions;
2076 bool foundInstalledInOrGroup = false;
2077 for(;;)
2078 {
2079 /* Skip if package is installed already, or is about to be */
2080 string target = Start.TargetPkg().FullName(true) + " ";
2081 pkgCache::PkgIterator const TarPkg = Start.TargetPkg();
2082 if (TarPkg->SelectedState == pkgCache::State::Install ||
2083 TarPkg->SelectedState == pkgCache::State::Hold ||
2084 Cache[Start.TargetPkg()].Install())
2085 {
2086 foundInstalledInOrGroup=true;
2087 break;
2088 }
2089
2090 /* Skip if we already saw it */
2091 if (int(SuggestsList.find(target)) != -1 || int(RecommendsList.find(target)) != -1)
2092 {
2093 foundInstalledInOrGroup=true;
2094 break;
2095 }
2096
2097 // this is a dep on a virtual pkg, check if any package that provides it
2098 // should be installed
2099 if(Start.TargetPkg().ProvidesList() != 0)
2100 {
2101 pkgCache::PrvIterator I = Start.TargetPkg().ProvidesList();
2102 for (; I.end() == false; ++I)
2103 {
2104 pkgCache::PkgIterator Pkg = I.OwnerPkg();
2105 if (Cache[Pkg].CandidateVerIter(Cache) == I.OwnerVer() &&
2106 Pkg.CurrentVer() != 0)
2107 foundInstalledInOrGroup=true;
2108 }
2109 }
2110
2111 if (Start->Type == pkgCache::Dep::Suggests)
2112 {
2113 SuggestsOrList += target;
2114 SuggestsOrVersions += string(Cache[Start.TargetPkg()].CandVersion) + "\n";
2115 }
2116
2117 if (Start->Type == pkgCache::Dep::Recommends)
2118 {
2119 RecommendsOrList += target;
2120 RecommendsOrVersions += string(Cache[Start.TargetPkg()].CandVersion) + "\n";
2121 }
2122
2123 if (Start >= End)
2124 break;
2125 ++Start;
2126 }
2127
2128 if(foundInstalledInOrGroup == false)
2129 {
2130 RecommendsList += RecommendsOrList;
2131 RecommendsVersions += RecommendsOrVersions;
2132 SuggestsList += SuggestsOrList;
2133 SuggestsVersions += SuggestsOrVersions;
2134 }
2135
2136 }
2137 }
2138
2139 ShowList(c1out,_("Suggested packages:"),SuggestsList,SuggestsVersions);
2140 ShowList(c1out,_("Recommended packages:"),RecommendsList,RecommendsVersions);
2141
2142 }
2143
2144 // if nothing changed in the cache, but only the automark information
2145 // we write the StateFile here, otherwise it will be written in
2146 // cache.commit()
2147 if (InstallAction.AutoMarkChanged > 0 &&
2148 Cache->DelCount() == 0 && Cache->InstCount() == 0 &&
2149 Cache->BadCount() == 0 &&
2150 _config->FindB("APT::Get::Simulate",false) == false)
2151 Cache->writeStateFile(NULL);
2152
2153 // See if we need to prompt
2154 // FIXME: check if really the packages in the set are going to be installed
2155 if (Cache->InstCount() == verset[MOD_INSTALL].size() && Cache->DelCount() == 0)
2156 return InstallPackages(Cache,false,false);
2157
2158 return InstallPackages(Cache,false);
2159 }
2160 /*}}}*/
2161 /* mark packages as automatically/manually installed. {{{*/
2162 bool DoMarkAuto(CommandLine &CmdL)
2163 {
2164 bool Action = true;
2165 int AutoMarkChanged = 0;
2166 OpTextProgress progress;
2167 CacheFile Cache;
2168 if (Cache.Open() == false)
2169 return false;
2170
2171 if (strcasecmp(CmdL.FileList[0],"markauto") == 0)
2172 Action = true;
2173 else if (strcasecmp(CmdL.FileList[0],"unmarkauto") == 0)
2174 Action = false;
2175
2176 for (const char **I = CmdL.FileList + 1; *I != 0; I++)
2177 {
2178 const char *S = *I;
2179 // Locate the package
2180 pkgCache::PkgIterator Pkg = Cache->FindPkg(S);
2181 if (Pkg.end() == true) {
2182 return _error->Error(_("Couldn't find package %s"),S);
2183 }
2184 else
2185 {
2186 if (!Action)
2187 ioprintf(c1out,_("%s set to manually installed.\n"), Pkg.Name());
2188 else
2189 ioprintf(c1out,_("%s set to automatically installed.\n"),
2190 Pkg.Name());
2191
2192 Cache->MarkAuto(Pkg,Action);
2193 AutoMarkChanged++;
2194 }
2195 }
2196
2197 _error->Notice(_("This command is deprecated. Please use 'apt-mark auto' and 'apt-mark manual' instead."));
2198
2199 if (AutoMarkChanged && ! _config->FindB("APT::Get::Simulate",false))
2200 return Cache->writeStateFile(NULL);
2201 return false;
2202 }
2203 /*}}}*/
2204 // DoDistUpgrade - Automatic smart upgrader /*{{{*/
2205 // ---------------------------------------------------------------------
2206 /* Intelligent upgrader that will install and remove packages at will */
2207 bool DoDistUpgrade(CommandLine &CmdL)
2208 {
2209 CacheFile Cache;
2210 if (Cache.OpenForInstall() == false || Cache.CheckDeps() == false)
2211 return false;
2212
2213 c0out << _("Calculating upgrade... ") << flush;
2214 if (pkgDistUpgrade(*Cache) == false)
2215 {
2216 c0out << _("Failed") << endl;
2217 ShowBroken(c1out,Cache,false);
2218 return false;
2219 }
2220
2221 c0out << _("Done") << endl;
2222
2223 return InstallPackages(Cache,true);
2224 }
2225 /*}}}*/
2226 // DoDSelectUpgrade - Do an upgrade by following dselects selections /*{{{*/
2227 // ---------------------------------------------------------------------
2228 /* Follows dselect's selections */
2229 bool DoDSelectUpgrade(CommandLine &CmdL)
2230 {
2231 CacheFile Cache;
2232 if (Cache.OpenForInstall() == false || Cache.CheckDeps() == false)
2233 return false;
2234
2235 pkgDepCache::ActionGroup group(Cache);
2236
2237 // Install everything with the install flag set
2238 pkgCache::PkgIterator I = Cache->PkgBegin();
2239 for (;I.end() != true; ++I)
2240 {
2241 /* Install the package only if it is a new install, the autoupgrader
2242 will deal with the rest */
2243 if (I->SelectedState == pkgCache::State::Install)
2244 Cache->MarkInstall(I,false);
2245 }
2246
2247 /* Now install their deps too, if we do this above then order of
2248 the status file is significant for | groups */
2249 for (I = Cache->PkgBegin();I.end() != true; ++I)
2250 {
2251 /* Install the package only if it is a new install, the autoupgrader
2252 will deal with the rest */
2253 if (I->SelectedState == pkgCache::State::Install)
2254 Cache->MarkInstall(I,true);
2255 }
2256
2257 // Apply erasures now, they override everything else.
2258 for (I = Cache->PkgBegin();I.end() != true; ++I)
2259 {
2260 // Remove packages
2261 if (I->SelectedState == pkgCache::State::DeInstall ||
2262 I->SelectedState == pkgCache::State::Purge)
2263 Cache->MarkDelete(I,I->SelectedState == pkgCache::State::Purge);
2264 }
2265
2266 /* Resolve any problems that dselect created, allupgrade cannot handle
2267 such things. We do so quite agressively too.. */
2268 if (Cache->BrokenCount() != 0)
2269 {
2270 pkgProblemResolver Fix(Cache);
2271
2272 // Hold back held packages.
2273 if (_config->FindB("APT::Ignore-Hold",false) == false)
2274 {
2275 for (pkgCache::PkgIterator I = Cache->PkgBegin(); I.end() == false; ++I)
2276 {
2277 if (I->SelectedState == pkgCache::State::Hold)
2278 {
2279 Fix.Protect(I);
2280 Cache->MarkKeep(I);
2281 }
2282 }
2283 }
2284
2285 if (Fix.Resolve() == false)
2286 {
2287 ShowBroken(c1out,Cache,false);
2288 return _error->Error(_("Internal error, problem resolver broke stuff"));
2289 }
2290 }
2291
2292 // Now upgrade everything
2293 if (pkgAllUpgrade(Cache) == false)
2294 {
2295 ShowBroken(c1out,Cache,false);
2296 return _error->Error(_("Internal error, problem resolver broke stuff"));
2297 }
2298
2299 return InstallPackages(Cache,false);
2300 }
2301 /*}}}*/
2302 // DoClean - Remove download archives /*{{{*/
2303 // ---------------------------------------------------------------------
2304 /* */
2305 bool DoClean(CommandLine &CmdL)
2306 {
2307 std::string const archivedir = _config->FindDir("Dir::Cache::archives");
2308 std::string const pkgcache = _config->FindFile("Dir::cache::pkgcache");
2309 std::string const srcpkgcache = _config->FindFile("Dir::cache::srcpkgcache");
2310
2311 if (_config->FindB("APT::Get::Simulate") == true)
2312 {
2313 cout << "Del " << archivedir << "* " << archivedir << "partial/*"<< endl
2314 << "Del " << pkgcache << " " << srcpkgcache << endl;
2315 return true;
2316 }
2317
2318 // Lock the archive directory
2319 FileFd Lock;
2320 if (_config->FindB("Debug::NoLocking",false) == false)
2321 {
2322 int lock_fd = GetLock(archivedir + "lock");
2323 if (lock_fd < 0)
2324 return _error->Error(_("Unable to lock the download directory"));
2325 Lock.Fd(lock_fd);
2326 }
2327
2328 pkgAcquire Fetcher;
2329 Fetcher.Clean(archivedir);
2330 Fetcher.Clean(archivedir + "partial/");
2331
2332 pkgCacheFile::RemoveCaches();
2333
2334 return true;
2335 }
2336 /*}}}*/
2337 // DoAutoClean - Smartly remove downloaded archives /*{{{*/
2338 // ---------------------------------------------------------------------
2339 /* This is similar to clean but it only purges things that cannot be
2340 downloaded, that is old versions of cached packages. */
2341 class LogCleaner : public pkgArchiveCleaner
2342 {
2343 protected:
2344 virtual void Erase(const char *File,string Pkg,string Ver,struct stat &St)
2345 {
2346 c1out << "Del " << Pkg << " " << Ver << " [" << SizeToStr(St.st_size) << "B]" << endl;
2347
2348 if (_config->FindB("APT::Get::Simulate") == false)
2349 unlink(File);
2350 };
2351 };
2352
2353 bool DoAutoClean(CommandLine &CmdL)
2354 {
2355 // Lock the archive directory
2356 FileFd Lock;
2357 if (_config->FindB("Debug::NoLocking",false) == false)
2358 {
2359 int lock_fd = GetLock(_config->FindDir("Dir::Cache::Archives") + "lock");
2360 if (lock_fd < 0)
2361 return _error->Error(_("Unable to lock the download directory"));
2362 Lock.Fd(lock_fd);
2363 }
2364
2365 CacheFile Cache;
2366 if (Cache.Open() == false)
2367 return false;
2368
2369 LogCleaner Cleaner;
2370
2371 return Cleaner.Go(_config->FindDir("Dir::Cache::archives"),*Cache) &&
2372 Cleaner.Go(_config->FindDir("Dir::Cache::archives") + "partial/",*Cache);
2373 }
2374 /*}}}*/
2375 // DoDownload - download a binary /*{{{*/
2376 // ---------------------------------------------------------------------
2377 bool DoDownload(CommandLine &CmdL)
2378 {
2379 CacheFile Cache;
2380 if (Cache.ReadOnlyOpen() == false)
2381 return false;
2382
2383 APT::CacheSetHelper helper(c0out);
2384 APT::VersionList verset = APT::VersionList::FromCommandLine(Cache,
2385 CmdL.FileList + 1, APT::VersionList::CANDIDATE, helper);
2386
2387 if (verset.empty() == true)
2388 return false;
2389
2390 pkgAcquire Fetcher;
2391 AcqTextStatus Stat(ScreenWidth, _config->FindI("quiet",0));
2392 if (_config->FindB("APT::Get::Print-URIs") == false)
2393 Fetcher.Setup(&Stat);
2394
2395 pkgRecords Recs(Cache);
2396 pkgSourceList *SrcList = Cache.GetSourceList();
2397 bool gotAll = true;
2398
2399 for (APT::VersionList::const_iterator Ver = verset.begin();
2400 Ver != verset.end();
2401 ++Ver)
2402 {
2403 string descr;
2404 // get the right version
2405 pkgCache::PkgIterator Pkg = Ver.ParentPkg();
2406 pkgRecords::Parser &rec=Recs.Lookup(Ver.FileList());
2407 pkgCache::VerFileIterator Vf = Ver.FileList();
2408 if (Vf.end() == true)
2409 {
2410 _error->Error("Can not find VerFile for %s in version %s", Pkg.FullName().c_str(), Ver.VerStr());
2411 gotAll = false;
2412 continue;
2413 }
2414 pkgCache::PkgFileIterator F = Vf.File();
2415 pkgIndexFile *index;
2416 if(SrcList->FindIndex(F, index) == false)
2417 {
2418 _error->Error(_("Can't find a source to download version '%s' of '%s'"), Ver.VerStr(), Pkg.FullName().c_str());
2419 gotAll = false;
2420 continue;
2421 }
2422 string uri = index->ArchiveURI(rec.FileName());
2423 strprintf(descr, _("Downloading %s %s"), Pkg.Name(), Ver.VerStr());
2424 // get the most appropriate hash
2425 HashString hash;
2426 if (rec.SHA512Hash() != "")
2427 hash = HashString("sha512", rec.SHA512Hash());
2428 else if (rec.SHA256Hash() != "")
2429 hash = HashString("sha256", rec.SHA256Hash());
2430 else if (rec.SHA1Hash() != "")
2431 hash = HashString("sha1", rec.SHA1Hash());
2432 else if (rec.MD5Hash() != "")
2433 hash = HashString("md5", rec.MD5Hash());
2434 // get the file
2435 new pkgAcqFile(&Fetcher, uri, hash.toStr(), (*Ver)->Size, descr, Pkg.Name(), ".");
2436 }
2437 if (gotAll == false)
2438 return false;
2439
2440 // Just print out the uris and exit if the --print-uris flag was used
2441 if (_config->FindB("APT::Get::Print-URIs") == true)
2442 {
2443 pkgAcquire::UriIterator I = Fetcher.UriBegin();
2444 for (; I != Fetcher.UriEnd(); ++I)
2445 cout << '\'' << I->URI << "' " << flNotDir(I->Owner->DestFile) << ' ' <<
2446 I->Owner->FileSize << ' ' << I->Owner->HashSum() << endl;
2447 return true;
2448 }
2449
2450 return (Fetcher.Run() == pkgAcquire::Continue);
2451 }
2452 /*}}}*/
2453 // DoCheck - Perform the check operation /*{{{*/
2454 // ---------------------------------------------------------------------
2455 /* Opening automatically checks the system, this command is mostly used
2456 for debugging */
2457 bool DoCheck(CommandLine &CmdL)
2458 {
2459 CacheFile Cache;
2460 Cache.Open();
2461 Cache.CheckDeps();
2462
2463 return true;
2464 }
2465 /*}}}*/
2466 // DoSource - Fetch a source archive /*{{{*/
2467 // ---------------------------------------------------------------------
2468 /* Fetch souce packages */
2469 struct DscFile
2470 {
2471 string Package;
2472 string Version;
2473 string Dsc;
2474 };
2475
2476 bool DoSource(CommandLine &CmdL)
2477 {
2478 CacheFile Cache;
2479 if (Cache.Open(false) == false)
2480 return false;
2481
2482 if (CmdL.FileSize() <= 1)
2483 return _error->Error(_("Must specify at least one package to fetch source for"));
2484
2485 // Read the source list
2486 if (Cache.BuildSourceList() == false)
2487 return false;
2488 pkgSourceList *List = Cache.GetSourceList();
2489
2490 // Create the text record parsers
2491 pkgRecords Recs(Cache);
2492 pkgSrcRecords SrcRecs(*List);
2493 if (_error->PendingError() == true)
2494 return false;
2495
2496 // Create the download object
2497 AcqTextStatus Stat(ScreenWidth,_config->FindI("quiet",0));
2498 pkgAcquire Fetcher;
2499 Fetcher.SetLog(&Stat);
2500
2501 DscFile *Dsc = new DscFile[CmdL.FileSize()];
2502
2503 // insert all downloaded uris into this set to avoid downloading them
2504 // twice
2505 set<string> queued;
2506
2507 // Diff only mode only fetches .diff files
2508 bool const diffOnly = _config->FindB("APT::Get::Diff-Only", false);
2509 // Tar only mode only fetches .tar files
2510 bool const tarOnly = _config->FindB("APT::Get::Tar-Only", false);
2511 // Dsc only mode only fetches .dsc files
2512 bool const dscOnly = _config->FindB("APT::Get::Dsc-Only", false);
2513
2514 // Load the requestd sources into the fetcher
2515 unsigned J = 0;
2516 for (const char **I = CmdL.FileList + 1; *I != 0; I++, J++)
2517 {
2518 string Src;
2519 pkgSrcRecords::Parser *Last = FindSrc(*I,Recs,SrcRecs,Src,*Cache);
2520
2521 if (Last == 0) {
2522 delete[] Dsc;
2523 return _error->Error(_("Unable to find a source package for %s"),Src.c_str());
2524 }
2525
2526 string srec = Last->AsStr();
2527 string::size_type pos = srec.find("\nVcs-");
2528 while (pos != string::npos)
2529 {
2530 pos += strlen("\nVcs-");
2531 string vcs = srec.substr(pos,srec.find(":",pos)-pos);
2532 if(vcs == "Browser")
2533 {
2534 pos = srec.find("\nVcs-", pos);
2535 continue;
2536 }
2537 pos += vcs.length()+2;
2538 string::size_type epos = srec.find("\n", pos);
2539 string uri = srec.substr(pos,epos-pos).c_str();
2540 ioprintf(c1out, _("NOTICE: '%s' packaging is maintained in "
2541 "the '%s' version control system at:\n"
2542 "%s\n"),
2543 Src.c_str(), vcs.c_str(), uri.c_str());
2544 if(vcs == "Bzr")
2545 ioprintf(c1out,_("Please use:\n"
2546 "bzr branch %s\n"
2547 "to retrieve the latest (possibly unreleased) "
2548 "updates to the package.\n"),
2549 uri.c_str());
2550 break;
2551 }
2552
2553 // Back track
2554 vector<pkgSrcRecords::File> Lst;
2555 if (Last->Files(Lst) == false) {
2556 delete[] Dsc;
2557 return false;
2558 }
2559
2560 // Load them into the fetcher
2561 for (vector<pkgSrcRecords::File>::const_iterator I = Lst.begin();
2562 I != Lst.end(); ++I)
2563 {
2564 // Try to guess what sort of file it is we are getting.
2565 if (I->Type == "dsc")
2566 {
2567 Dsc[J].Package = Last->Package();
2568 Dsc[J].Version = Last->Version();
2569 Dsc[J].Dsc = flNotDir(I->Path);
2570 }
2571
2572 // Handle the only options so that multiple can be used at once
2573 if (diffOnly == true || tarOnly == true || dscOnly == true)
2574 {
2575 if ((diffOnly == true && I->Type == "diff") ||
2576 (tarOnly == true && I->Type == "tar") ||
2577 (dscOnly == true && I->Type == "dsc"))
2578 ; // Fine, we want this file downloaded
2579 else
2580 continue;
2581 }
2582
2583 // don't download the same uri twice (should this be moved to
2584 // the fetcher interface itself?)
2585 if(queued.find(Last->Index().ArchiveURI(I->Path)) != queued.end())
2586 continue;
2587 queued.insert(Last->Index().ArchiveURI(I->Path));
2588
2589 // check if we have a file with that md5 sum already localy
2590 if(!I->MD5Hash.empty() && FileExists(flNotDir(I->Path)))
2591 {
2592 FileFd Fd(flNotDir(I->Path), FileFd::ReadOnly);
2593 MD5Summation sum;
2594 sum.AddFD(Fd.Fd(), Fd.Size());
2595 Fd.Close();
2596 if((string)sum.Result() == I->MD5Hash)
2597 {
2598 ioprintf(c1out,_("Skipping already downloaded file '%s'\n"),
2599 flNotDir(I->Path).c_str());
2600 continue;
2601 }
2602 }
2603
2604 new pkgAcqFile(&Fetcher,Last->Index().ArchiveURI(I->Path),
2605 I->MD5Hash,I->Size,
2606 Last->Index().SourceInfo(*Last,*I),Src);
2607 }
2608 }
2609
2610 // Display statistics
2611 unsigned long long FetchBytes = Fetcher.FetchNeeded();
2612 unsigned long long FetchPBytes = Fetcher.PartialPresent();
2613 unsigned long long DebBytes = Fetcher.TotalNeeded();
2614
2615 // Check for enough free space
2616 struct statvfs Buf;
2617 string OutputDir = ".";
2618 if (statvfs(OutputDir.c_str(),&Buf) != 0) {
2619 delete[] Dsc;
2620 if (errno == EOVERFLOW)
2621 return _error->WarningE("statvfs",_("Couldn't determine free space in %s"),
2622 OutputDir.c_str());
2623 else
2624 return _error->Errno("statvfs",_("Couldn't determine free space in %s"),
2625 OutputDir.c_str());
2626 } else if (unsigned(Buf.f_bfree) < (FetchBytes - FetchPBytes)/Buf.f_bsize)
2627 {
2628 struct statfs Stat;
2629 if (statfs(OutputDir.c_str(),&Stat) != 0
2630 #if HAVE_STRUCT_STATFS_F_TYPE
2631 || unsigned(Stat.f_type) != RAMFS_MAGIC
2632 #endif
2633 ) {
2634 delete[] Dsc;
2635 return _error->Error(_("You don't have enough free space in %s"),
2636 OutputDir.c_str());
2637 }
2638 }
2639
2640 // Number of bytes
2641 if (DebBytes != FetchBytes)
2642 //TRANSLATOR: The required space between number and unit is already included
2643 // in the replacement strings, so %sB will be correctly translate in e.g. 1,5 MB
2644 ioprintf(c1out,_("Need to get %sB/%sB of source archives.\n"),
2645 SizeToStr(FetchBytes).c_str(),SizeToStr(DebBytes).c_str());
2646 else
2647 //TRANSLATOR: The required space between number and unit is already included
2648 // in the replacement string, so %sB will be correctly translate in e.g. 1,5 MB
2649 ioprintf(c1out,_("Need to get %sB of source archives.\n"),
2650 SizeToStr(DebBytes).c_str());
2651
2652 if (_config->FindB("APT::Get::Simulate",false) == true)
2653 {
2654 for (unsigned I = 0; I != J; I++)
2655 ioprintf(cout,_("Fetch source %s\n"),Dsc[I].Package.c_str());
2656 delete[] Dsc;
2657 return true;
2658 }
2659
2660 // Just print out the uris an exit if the --print-uris flag was used
2661 if (_config->FindB("APT::Get::Print-URIs") == true)
2662 {
2663 pkgAcquire::UriIterator I = Fetcher.UriBegin();
2664 for (; I != Fetcher.UriEnd(); ++I)
2665 cout << '\'' << I->URI << "' " << flNotDir(I->Owner->DestFile) << ' ' <<
2666 I->Owner->FileSize << ' ' << I->Owner->HashSum() << endl;
2667 delete[] Dsc;
2668 return true;
2669 }
2670
2671 // Run it
2672 if (Fetcher.Run() == pkgAcquire::Failed)
2673 {
2674 delete[] Dsc;
2675 return false;
2676 }
2677
2678 // Print error messages
2679 bool Failed = false;
2680 for (pkgAcquire::ItemIterator I = Fetcher.ItemsBegin(); I != Fetcher.ItemsEnd(); ++I)
2681 {
2682 if ((*I)->Status == pkgAcquire::Item::StatDone &&
2683 (*I)->Complete == true)
2684 continue;
2685
2686 fprintf(stderr,_("Failed to fetch %s %s\n"),(*I)->DescURI().c_str(),
2687 (*I)->ErrorText.c_str());
2688 Failed = true;
2689 }
2690 if (Failed == true)
2691 {
2692 delete[] Dsc;
2693 return _error->Error(_("Failed to fetch some archives."));
2694 }
2695
2696 if (_config->FindB("APT::Get::Download-only",false) == true)
2697 {
2698 c1out << _("Download complete and in download only mode") << endl;
2699 delete[] Dsc;
2700 return true;
2701 }
2702
2703 // Unpack the sources
2704 pid_t Process = ExecFork();
2705
2706 if (Process == 0)
2707 {
2708 bool const fixBroken = _config->FindB("APT::Get::Fix-Broken", false);
2709 for (unsigned I = 0; I != J; ++I)
2710 {
2711 string Dir = Dsc[I].Package + '-' + Cache->VS().UpstreamVersion(Dsc[I].Version.c_str());
2712
2713 // Diff only mode only fetches .diff files
2714 if (_config->FindB("APT::Get::Diff-Only",false) == true ||
2715 _config->FindB("APT::Get::Tar-Only",false) == true ||
2716 Dsc[I].Dsc.empty() == true)
2717 continue;
2718
2719 // See if the package is already unpacked
2720 struct stat Stat;
2721 if (fixBroken == false && stat(Dir.c_str(),&Stat) == 0 &&
2722 S_ISDIR(Stat.st_mode) != 0)
2723 {
2724 ioprintf(c0out ,_("Skipping unpack of already unpacked source in %s\n"),
2725 Dir.c_str());
2726 }
2727 else
2728 {
2729 // Call dpkg-source
2730 char S[500];
2731 snprintf(S,sizeof(S),"%s -x %s",
2732 _config->Find("Dir::Bin::dpkg-source","dpkg-source").c_str(),
2733 Dsc[I].Dsc.c_str());
2734 if (system(S) != 0)
2735 {
2736 fprintf(stderr,_("Unpack command '%s' failed.\n"),S);
2737 fprintf(stderr,_("Check if the 'dpkg-dev' package is installed.\n"));
2738 _exit(1);
2739 }
2740 }
2741
2742 // Try to compile it with dpkg-buildpackage
2743 if (_config->FindB("APT::Get::Compile",false) == true)
2744 {
2745 string buildopts = _config->Find("APT::Get::Host-Architecture");
2746 if (buildopts.empty() == false)
2747 buildopts = "-a" + buildopts + " ";
2748 buildopts.append(_config->Find("DPkg::Build-Options","-b -uc"));
2749
2750 // Call dpkg-buildpackage
2751 char S[500];
2752 snprintf(S,sizeof(S),"cd %s && %s %s",
2753 Dir.c_str(),
2754 _config->Find("Dir::Bin::dpkg-buildpackage","dpkg-buildpackage").c_str(),
2755 buildopts.c_str());
2756
2757 if (system(S) != 0)
2758 {
2759 fprintf(stderr,_("Build command '%s' failed.\n"),S);
2760 _exit(1);
2761 }
2762 }
2763 }
2764
2765 _exit(0);
2766 }
2767 delete[] Dsc;
2768
2769 // Wait for the subprocess
2770 int Status = 0;
2771 while (waitpid(Process,&Status,0) != Process)
2772 {
2773 if (errno == EINTR)
2774 continue;
2775 return _error->Errno("waitpid","Couldn't wait for subprocess");
2776 }
2777
2778 if (WIFEXITED(Status) == 0 || WEXITSTATUS(Status) != 0)
2779 return _error->Error(_("Child process failed"));
2780
2781 return true;
2782 }
2783 /*}}}*/
2784 // DoBuildDep - Install/removes packages to satisfy build dependencies /*{{{*/
2785 // ---------------------------------------------------------------------
2786 /* This function will look at the build depends list of the given source
2787 package and install the necessary packages to make it true, or fail. */
2788 bool DoBuildDep(CommandLine &CmdL)
2789 {
2790 CacheFile Cache;
2791
2792 _config->Set("APT::Install-Recommends", false);
2793
2794 if (Cache.Open(true) == false)
2795 return false;
2796
2797 if (CmdL.FileSize() <= 1)
2798 return _error->Error(_("Must specify at least one package to check builddeps for"));
2799
2800 // Read the source list
2801 if (Cache.BuildSourceList() == false)
2802 return false;
2803 pkgSourceList *List = Cache.GetSourceList();
2804
2805 // Create the text record parsers
2806 pkgRecords Recs(Cache);
2807 pkgSrcRecords SrcRecs(*List);
2808 if (_error->PendingError() == true)
2809 return false;
2810
2811 // Create the download object
2812 AcqTextStatus Stat(ScreenWidth,_config->FindI("quiet",0));
2813 pkgAcquire Fetcher;
2814 if (Fetcher.Setup(&Stat) == false)
2815 return false;
2816
2817 bool StripMultiArch;
2818 string hostArch = _config->Find("APT::Get::Host-Architecture");
2819 if (hostArch.empty() == false)
2820 {
2821 std::vector<std::string> archs = APT::Configuration::getArchitectures();
2822 if (std::find(archs.begin(), archs.end(), hostArch) == archs.end())
2823 return _error->Error(_("No architecture information available for %s. See apt.conf(5) APT::Architectures for setup"), hostArch.c_str());
2824 StripMultiArch = false;
2825 }
2826 else
2827 StripMultiArch = true;
2828
2829 unsigned J = 0;
2830 for (const char **I = CmdL.FileList + 1; *I != 0; I++, J++)
2831 {
2832 string Src;
2833 pkgSrcRecords::Parser *Last = FindSrc(*I,Recs,SrcRecs,Src,*Cache);
2834 if (Last == 0)
2835 return _error->Error(_("Unable to find a source package for %s"),Src.c_str());
2836
2837 // Process the build-dependencies
2838 vector<pkgSrcRecords::Parser::BuildDepRec> BuildDeps;
2839 // FIXME: Can't specify architecture to use for [wildcard] matching, so switch default arch temporary
2840 if (hostArch.empty() == false)
2841 {
2842 std::string nativeArch = _config->Find("APT::Architecture");
2843 _config->Set("APT::Architecture", hostArch);
2844 bool Success = Last->BuildDepends(BuildDeps, _config->FindB("APT::Get::Arch-Only", false), StripMultiArch);
2845 _config->Set("APT::Architecture", nativeArch);
2846 if (Success == false)
2847 return _error->Error(_("Unable to get build-dependency information for %s"),Src.c_str());
2848 }
2849 else if (Last->BuildDepends(BuildDeps, _config->FindB("APT::Get::Arch-Only", false), StripMultiArch) == false)
2850 return _error->Error(_("Unable to get build-dependency information for %s"),Src.c_str());
2851
2852 // Also ensure that build-essential packages are present
2853 Configuration::Item const *Opts = _config->Tree("APT::Build-Essential");
2854 if (Opts)
2855 Opts = Opts->Child;
2856 for (; Opts; Opts = Opts->Next)
2857 {
2858 if (Opts->Value.empty() == true)
2859 continue;
2860
2861 pkgSrcRecords::Parser::BuildDepRec rec;
2862 rec.Package = Opts->Value;
2863 rec.Type = pkgSrcRecords::Parser::BuildDependIndep;
2864 rec.Op = 0;
2865 BuildDeps.push_back(rec);
2866 }
2867
2868 if (BuildDeps.empty() == true)
2869 {
2870 ioprintf(c1out,_("%s has no build depends.\n"),Src.c_str());
2871 continue;
2872 }
2873
2874 // Install the requested packages
2875 vector <pkgSrcRecords::Parser::BuildDepRec>::iterator D;
2876 pkgProblemResolver Fix(Cache);
2877 bool skipAlternatives = false; // skip remaining alternatives in an or group
2878 for (D = BuildDeps.begin(); D != BuildDeps.end(); ++D)
2879 {
2880 bool hasAlternatives = (((*D).Op & pkgCache::Dep::Or) == pkgCache::Dep::Or);
2881
2882 if (skipAlternatives == true)
2883 {
2884 /*
2885 * if there are alternatives, we've already picked one, so skip
2886 * the rest
2887 *
2888 * TODO: this means that if there's a build-dep on A|B and B is
2889 * installed, we'll still try to install A; more importantly,
2890 * if A is currently broken, we cannot go back and try B. To fix
2891 * this would require we do a Resolve cycle for each package we
2892 * add to the install list. Ugh
2893 */
2894 if (!hasAlternatives)
2895 skipAlternatives = false; // end of or group
2896 continue;
2897 }
2898
2899 if ((*D).Type == pkgSrcRecords::Parser::BuildConflict ||
2900 (*D).Type == pkgSrcRecords::Parser::BuildConflictIndep)
2901 {
2902 pkgCache::GrpIterator Grp = Cache->FindGrp((*D).Package);
2903 // Build-conflicts on unknown packages are silently ignored
2904 if (Grp.end() == true)
2905 continue;
2906
2907 for (pkgCache::PkgIterator Pkg = Grp.PackageList(); Pkg.end() == false; Pkg = Grp.NextPkg(Pkg))
2908 {
2909 pkgCache::VerIterator IV = (*Cache)[Pkg].InstVerIter(*Cache);
2910 /*
2911 * Remove if we have an installed version that satisfies the
2912 * version criteria
2913 */
2914 if (IV.end() == false &&
2915 Cache->VS().CheckDep(IV.VerStr(),(*D).Op,(*D).Version.c_str()) == true)
2916 TryToInstallBuildDep(Pkg,Cache,Fix,true,false);
2917 }
2918 }
2919 else // BuildDep || BuildDepIndep
2920 {
2921 if (_config->FindB("Debug::BuildDeps",false) == true)
2922 cout << "Looking for " << (*D).Package << "...\n";
2923
2924 pkgCache::PkgIterator Pkg;
2925
2926 // Cross-Building?
2927 if (StripMultiArch == false && D->Type != pkgSrcRecords::Parser::BuildDependIndep)
2928 {
2929 size_t const colon = D->Package.find(":");
2930 if (colon != string::npos)
2931 {
2932 if (strcmp(D->Package.c_str() + colon, ":any") == 0 || strcmp(D->Package.c_str() + colon, ":native") == 0)
2933 Pkg = Cache->FindPkg(D->Package.substr(0,colon));
2934 else
2935 Pkg = Cache->FindPkg(D->Package);
2936 }
2937 else
2938 Pkg = Cache->FindPkg(D->Package, hostArch);
2939
2940 // a bad version either is invalid or doesn't satify dependency
2941 #define BADVER(Ver) (Ver.end() == true || \
2942 (D->Version.empty() == false && \
2943 Cache->VS().CheckDep(Ver.VerStr(),D->Op,D->Version.c_str()) == false))
2944
2945 APT::VersionList verlist;
2946 if (Pkg.end() == false)
2947 {
2948 pkgCache::VerIterator Ver = (*Cache)[Pkg].InstVerIter(*Cache);
2949 if (BADVER(Ver) == false)
2950 verlist.insert(Ver);
2951 Ver = (*Cache)[Pkg].CandidateVerIter(*Cache);
2952 if (BADVER(Ver) == false)
2953 verlist.insert(Ver);
2954 }
2955 if (verlist.empty() == true)
2956 {
2957 pkgCache::PkgIterator BuildPkg = Cache->FindPkg(D->Package, "native");
2958 if (BuildPkg.end() == false && Pkg != BuildPkg)
2959 {
2960 pkgCache::VerIterator Ver = (*Cache)[BuildPkg].InstVerIter(*Cache);
2961 if (BADVER(Ver) == false)
2962 verlist.insert(Ver);
2963 Ver = (*Cache)[BuildPkg].CandidateVerIter(*Cache);
2964 if (BADVER(Ver) == false)
2965 verlist.insert(Ver);
2966 }
2967 }
2968 #undef BADVER
2969
2970 string forbidden;
2971 // We need to decide if host or build arch, so find a version we can look at
2972 APT::VersionList::const_iterator Ver = verlist.begin();
2973 for (; Ver != verlist.end(); ++Ver)
2974 {
2975 forbidden.clear();
2976 if (Ver->MultiArch == pkgCache::Version::None || Ver->MultiArch == pkgCache::Version::All)
2977 {
2978 if (colon == string::npos)
2979 Pkg = Ver.ParentPkg().Group().FindPkg(hostArch);
2980 else if (strcmp(D->Package.c_str() + colon, ":any") == 0)
2981 forbidden = "Multi-Arch: none";
2982 else if (strcmp(D->Package.c_str() + colon, ":native") == 0)
2983 Pkg = Ver.ParentPkg().Group().FindPkg("native");
2984 }
2985 else if (Ver->MultiArch == pkgCache::Version::Same)
2986 {
2987 if (colon == string::npos)
2988 Pkg = Ver.ParentPkg().Group().FindPkg(hostArch);
2989 else if (strcmp(D->Package.c_str() + colon, ":any") == 0)
2990 forbidden = "Multi-Arch: same";
2991 else if (strcmp(D->Package.c_str() + colon, ":native") == 0)
2992 Pkg = Ver.ParentPkg().Group().FindPkg("native");
2993 }
2994 else if ((Ver->MultiArch & pkgCache::Version::Foreign) == pkgCache::Version::Foreign)
2995 {
2996 if (colon == string::npos)
2997 Pkg = Ver.ParentPkg().Group().FindPkg("native");
2998 else if (strcmp(D->Package.c_str() + colon, ":any") == 0 ||
2999 strcmp(D->Package.c_str() + colon, ":native") == 0)
3000 forbidden = "Multi-Arch: foreign";
3001 }
3002 else if ((Ver->MultiArch & pkgCache::Version::Allowed) == pkgCache::Version::Allowed)
3003 {
3004 if (colon == string::npos)
3005 Pkg = Ver.ParentPkg().Group().FindPkg(hostArch);
3006 else if (strcmp(D->Package.c_str() + colon, ":any") == 0)
3007 {
3008 // prefer any installed over preferred non-installed architectures
3009 pkgCache::GrpIterator Grp = Ver.ParentPkg().Group();
3010 // we don't check for version here as we are better of with upgrading than remove and install
3011 for (Pkg = Grp.PackageList(); Pkg.end() == false; Pkg = Grp.NextPkg(Pkg))
3012 if (Pkg.CurrentVer().end() == false)
3013 break;
3014 if (Pkg.end() == true)
3015 Pkg = Grp.FindPreferredPkg(true);
3016 }
3017 else if (strcmp(D->Package.c_str() + colon, ":native") == 0)
3018 Pkg = Ver.ParentPkg().Group().FindPkg("native");
3019 }
3020
3021 if (forbidden.empty() == false)
3022 {
3023 if (_config->FindB("Debug::BuildDeps",false) == true)
3024 cout << D->Package.substr(colon, string::npos) << " is not allowed from " << forbidden << " package " << (*D).Package << " (" << Ver.VerStr() << ")" << endl;
3025 continue;
3026 }
3027
3028 //we found a good version
3029 break;
3030 }
3031 if (Ver == verlist.end())
3032 {
3033 if (_config->FindB("Debug::BuildDeps",false) == true)
3034 cout << " No multiarch info as we have no satisfying installed nor candidate for " << D->Package << " on build or host arch" << endl;
3035
3036 if (forbidden.empty() == false)
3037 {
3038 if (hasAlternatives)
3039 continue;
3040 return _error->Error(_("%s dependency for %s can't be satisfied "
3041 "because %s is not allowed on '%s' packages"),
3042 Last->BuildDepType(D->Type), Src.c_str(),
3043 D->Package.c_str(), forbidden.c_str());
3044 }
3045 }
3046 }
3047 else
3048 Pkg = Cache->FindPkg(D->Package);
3049
3050 if (Pkg.end() == true || (Pkg->VersionList == 0 && Pkg->ProvidesList == 0))
3051 {
3052 if (_config->FindB("Debug::BuildDeps",false) == true)
3053 cout << " (not found)" << (*D).Package << endl;
3054
3055 if (hasAlternatives)
3056 continue;
3057
3058 return _error->Error(_("%s dependency for %s cannot be satisfied "
3059 "because the package %s cannot be found"),
3060 Last->BuildDepType((*D).Type),Src.c_str(),
3061 (*D).Package.c_str());
3062 }
3063
3064 pkgCache::VerIterator IV = (*Cache)[Pkg].InstVerIter(*Cache);
3065 if (IV.end() == false)
3066 {
3067 if (_config->FindB("Debug::BuildDeps",false) == true)
3068 cout << " Is installed\n";
3069
3070 if (D->Version.empty() == true ||
3071 Cache->VS().CheckDep(IV.VerStr(),(*D).Op,(*D).Version.c_str()) == true)
3072 {
3073 skipAlternatives = hasAlternatives;
3074 continue;
3075 }
3076
3077 if (_config->FindB("Debug::BuildDeps",false) == true)
3078 cout << " ...but the installed version doesn't meet the version requirement\n";
3079
3080 if (((*D).Op & pkgCache::Dep::LessEq) == pkgCache::Dep::LessEq)
3081 return _error->Error(_("Failed to satisfy %s dependency for %s: Installed package %s is too new"),
3082 Last->BuildDepType((*D).Type), Src.c_str(), Pkg.FullName(true).c_str());
3083 }
3084
3085 // Only consider virtual packages if there is no versioned dependency
3086 if ((*D).Version.empty() == true)
3087 {
3088 /*
3089 * If this is a virtual package, we need to check the list of
3090 * packages that provide it and see if any of those are
3091 * installed
3092 */
3093 pkgCache::PrvIterator Prv = Pkg.ProvidesList();
3094 for (; Prv.end() != true; ++Prv)
3095 {
3096 if (_config->FindB("Debug::BuildDeps",false) == true)
3097 cout << " Checking provider " << Prv.OwnerPkg().FullName() << endl;
3098
3099 if ((*Cache)[Prv.OwnerPkg()].InstVerIter(*Cache).end() == false)
3100 break;
3101 }
3102
3103 if (Prv.end() == false)
3104 {
3105 if (_config->FindB("Debug::BuildDeps",false) == true)
3106 cout << " Is provided by installed package " << Prv.OwnerPkg().FullName() << endl;
3107 skipAlternatives = hasAlternatives;
3108 continue;
3109 }
3110 }
3111 else // versioned dependency
3112 {
3113 pkgCache::VerIterator CV = (*Cache)[Pkg].CandidateVerIter(*Cache);
3114 if (CV.end() == true ||
3115 Cache->VS().CheckDep(CV.VerStr(),(*D).Op,(*D).Version.c_str()) == false)
3116 {
3117 if (hasAlternatives)
3118 continue;
3119 else if (CV.end() == false)
3120 return _error->Error(_("%s dependency for %s cannot be satisfied "
3121 "because candidate version of package %s "
3122 "can't satisfy version requirements"),
3123 Last->BuildDepType(D->Type), Src.c_str(),
3124 D->Package.c_str());
3125 else
3126 return _error->Error(_("%s dependency for %s cannot be satisfied "
3127 "because package %s has no candidate version"),
3128 Last->BuildDepType(D->Type), Src.c_str(),
3129 D->Package.c_str());
3130 }
3131 }
3132
3133 if (TryToInstallBuildDep(Pkg,Cache,Fix,false,false,false) == true)
3134 {
3135 // We successfully installed something; skip remaining alternatives
3136 skipAlternatives = hasAlternatives;
3137 if(_config->FindB("APT::Get::Build-Dep-Automatic", false) == true)
3138 Cache->MarkAuto(Pkg, true);
3139 continue;
3140 }
3141 else if (hasAlternatives)
3142 {
3143 if (_config->FindB("Debug::BuildDeps",false) == true)
3144 cout << " Unsatisfiable, trying alternatives\n";
3145 continue;
3146 }
3147 else
3148 {
3149 return _error->Error(_("Failed to satisfy %s dependency for %s: %s"),
3150 Last->BuildDepType((*D).Type),
3151 Src.c_str(),
3152 (*D).Package.c_str());
3153 }
3154 }
3155 }
3156
3157 if (Fix.Resolve(true) == false)
3158 _error->Discard();
3159
3160 // Now we check the state of the packages,
3161 if (Cache->BrokenCount() != 0)
3162 {
3163 ShowBroken(cout, Cache, false);
3164 return _error->Error(_("Build-dependencies for %s could not be satisfied."),*I);
3165 }
3166 }
3167
3168 if (InstallPackages(Cache, false, true) == false)
3169 return _error->Error(_("Failed to process build dependencies"));
3170 return true;
3171 }
3172 /*}}}*/
3173 // GetChangelogPath - return a path pointing to a changelog file or dir /*{{{*/
3174 // ---------------------------------------------------------------------
3175 /* This returns a "path" string for the changelog url construction.
3176 * Please note that its not complete, it either needs a "/changelog"
3177 * appended (for the packages.debian.org/changelogs site) or a
3178 * ".changelog" (for third party sites that store the changelog in the
3179 * pool/ next to the deb itself)
3180 * Example return: "pool/main/a/apt/apt_0.8.8ubuntu3"
3181 */
3182 string GetChangelogPath(CacheFile &Cache,
3183 pkgCache::PkgIterator Pkg,
3184 pkgCache::VerIterator Ver)
3185 {
3186 string path;
3187
3188 pkgRecords Recs(Cache);
3189 pkgRecords::Parser &rec=Recs.Lookup(Ver.FileList());
3190 string srcpkg = rec.SourcePkg().empty() ? Pkg.Name() : rec.SourcePkg();
3191 string ver = Ver.VerStr();
3192 // if there is a source version it always wins
3193 if (rec.SourceVer() != "")
3194 ver = rec.SourceVer();
3195 path = flNotFile(rec.FileName());
3196 path += srcpkg + "_" + StripEpoch(ver);
3197 return path;
3198 }
3199 /*}}}*/
3200 // GuessThirdPartyChangelogUri - return url /*{{{*/
3201 // ---------------------------------------------------------------------
3202 /* Contruct a changelog file path for third party sites that do not use
3203 * packages.debian.org/changelogs
3204 * This simply uses the ArchiveURI() of the source pkg and looks for
3205 * a .changelog file there, Example for "mediabuntu":
3206 * apt-get changelog mplayer-doc:
3207 * http://packages.medibuntu.org/pool/non-free/m/mplayer/mplayer_1.0~rc4~try1.dsfg1-1ubuntu1+medibuntu1.changelog
3208 */
3209 bool GuessThirdPartyChangelogUri(CacheFile &Cache,
3210 pkgCache::PkgIterator Pkg,
3211 pkgCache::VerIterator Ver,
3212 string &out_uri)
3213 {
3214 // get the binary deb server path
3215 pkgCache::VerFileIterator Vf = Ver.FileList();
3216 if (Vf.end() == true)
3217 return false;
3218 pkgCache::PkgFileIterator F = Vf.File();
3219 pkgIndexFile *index;
3220 pkgSourceList *SrcList = Cache.GetSourceList();
3221 if(SrcList->FindIndex(F, index) == false)
3222 return false;
3223
3224 // get archive uri for the binary deb
3225 string path_without_dot_changelog = GetChangelogPath(Cache, Pkg, Ver);
3226 out_uri = index->ArchiveURI(path_without_dot_changelog + ".changelog");
3227
3228 // now strip away the filename and add srcpkg_srcver.changelog
3229 return true;
3230 }
3231 /*}}}*/
3232 // DownloadChangelog - Download the changelog /*{{{*/
3233 // ---------------------------------------------------------------------
3234 bool DownloadChangelog(CacheFile &CacheFile, pkgAcquire &Fetcher,
3235 pkgCache::VerIterator Ver, string targetfile)
3236 /* Download a changelog file for the given package version to
3237 * targetfile. This will first try the server from Apt::Changelogs::Server
3238 * (http://packages.debian.org/changelogs by default) and if that gives
3239 * a 404 tries to get it from the archive directly (see
3240 * GuessThirdPartyChangelogUri for details how)
3241 */
3242 {
3243 string path;
3244 string descr;
3245 string server;
3246 string changelog_uri;
3247
3248 // data structures we need
3249 pkgCache::PkgIterator Pkg = Ver.ParentPkg();
3250
3251 // make the server root configurable
3252 server = _config->Find("Apt::Changelogs::Server",
3253 "http://packages.debian.org/changelogs");
3254 path = GetChangelogPath(CacheFile, Pkg, Ver);
3255 strprintf(changelog_uri, "%s/%s/changelog", server.c_str(), path.c_str());
3256 if (_config->FindB("APT::Get::Print-URIs", false) == true)
3257 {
3258 std::cout << '\'' << changelog_uri << '\'' << std::endl;
3259 return true;
3260 }
3261
3262 strprintf(descr, _("Changelog for %s (%s)"), Pkg.Name(), changelog_uri.c_str());
3263 // queue it
3264 new pkgAcqFile(&Fetcher, changelog_uri, "", 0, descr, Pkg.Name(), "ignored", targetfile);
3265
3266 // try downloading it, if that fails, try third-party-changelogs location
3267 // FIXME: Fetcher.Run() is "Continue" even if I get a 404?!?
3268 Fetcher.Run();
3269 if (!FileExists(targetfile))
3270 {
3271 string third_party_uri;
3272 if (GuessThirdPartyChangelogUri(CacheFile, Pkg, Ver, third_party_uri))
3273 {
3274 strprintf(descr, _("Changelog for %s (%s)"), Pkg.Name(), third_party_uri.c_str());
3275 new pkgAcqFile(&Fetcher, third_party_uri, "", 0, descr, Pkg.Name(), "ignored", targetfile);
3276 Fetcher.Run();
3277 }
3278 }
3279
3280 if (FileExists(targetfile))
3281 return true;
3282
3283 // error
3284 return _error->Error("changelog download failed");
3285 }
3286 /*}}}*/
3287 // DisplayFileInPager - Display File with pager /*{{{*/
3288 void DisplayFileInPager(string filename)
3289 {
3290 pid_t Process = ExecFork();
3291 if (Process == 0)
3292 {
3293 const char *Args[3];
3294 Args[0] = "/usr/bin/sensible-pager";
3295 Args[1] = filename.c_str();
3296 Args[2] = 0;
3297 execvp(Args[0],(char **)Args);
3298 exit(100);
3299 }
3300
3301 // Wait for the subprocess
3302 ExecWait(Process, "sensible-pager", false);
3303 }
3304 /*}}}*/
3305 // DoChangelog - Get changelog from the command line /*{{{*/
3306 // ---------------------------------------------------------------------
3307 bool DoChangelog(CommandLine &CmdL)
3308 {
3309 CacheFile Cache;
3310 if (Cache.ReadOnlyOpen() == false)
3311 return false;
3312
3313 APT::CacheSetHelper helper(c0out);
3314 APT::VersionList verset = APT::VersionList::FromCommandLine(Cache,
3315 CmdL.FileList + 1, APT::VersionList::CANDIDATE, helper);
3316 if (verset.empty() == true)
3317 return false;
3318 pkgAcquire Fetcher;
3319
3320 if (_config->FindB("APT::Get::Print-URIs", false) == true)
3321 {
3322 bool Success = true;
3323 for (APT::VersionList::const_iterator Ver = verset.begin();
3324 Ver != verset.end(); ++Ver)
3325 Success &= DownloadChangelog(Cache, Fetcher, Ver, "");
3326 return Success;
3327 }
3328
3329 AcqTextStatus Stat(ScreenWidth, _config->FindI("quiet",0));
3330 Fetcher.Setup(&Stat);
3331
3332 bool const downOnly = _config->FindB("APT::Get::Download-Only", false);
3333
3334 char tmpname[100];
3335 char* tmpdir = NULL;
3336 if (downOnly == false)
3337 {
3338 const char* const tmpDir = getenv("TMPDIR");
3339 if (tmpDir != NULL && *tmpDir != '\0')
3340 snprintf(tmpname, sizeof(tmpname), "%s/apt-changelog-XXXXXX", tmpDir);
3341 else
3342 strncpy(tmpname, "/tmp/apt-changelog-XXXXXX", sizeof(tmpname));
3343 tmpdir = mkdtemp(tmpname);
3344 if (tmpdir == NULL)
3345 return _error->Errno("mkdtemp", "mkdtemp failed");
3346 }
3347
3348 for (APT::VersionList::const_iterator Ver = verset.begin();
3349 Ver != verset.end();
3350 ++Ver)
3351 {
3352 string changelogfile;
3353 if (downOnly == false)
3354 changelogfile.append(tmpname).append("changelog");
3355 else
3356 changelogfile.append(Ver.ParentPkg().Name()).append(".changelog");
3357 if (DownloadChangelog(Cache, Fetcher, Ver, changelogfile) && downOnly == false)
3358 {
3359 DisplayFileInPager(changelogfile);
3360 // cleanup temp file
3361 unlink(changelogfile.c_str());
3362 }
3363 }
3364 // clenaup tmp dir
3365 if (tmpdir != NULL)
3366 rmdir(tmpdir);
3367 return true;
3368 }
3369 /*}}}*/
3370 // DoMoo - Never Ask, Never Tell /*{{{*/
3371 // ---------------------------------------------------------------------
3372 /* */
3373 bool DoMoo(CommandLine &CmdL)
3374 {
3375 cout <<
3376 " (__) \n"
3377 " (oo) \n"
3378 " /------\\/ \n"
3379 " / | || \n"
3380 " * /\\---/\\ \n"
3381 " ~~ ~~ \n"
3382 "....\"Have you mooed today?\"...\n";
3383
3384 return true;
3385 }
3386 /*}}}*/
3387 // ShowHelp - Show a help screen /*{{{*/
3388 // ---------------------------------------------------------------------
3389 /* */
3390 bool ShowHelp(CommandLine &CmdL)
3391 {
3392 ioprintf(cout,_("%s %s for %s compiled on %s %s\n"),PACKAGE,PACKAGE_VERSION,
3393 COMMON_ARCH,__DATE__,__TIME__);
3394
3395 if (_config->FindB("version") == true)
3396 {
3397 cout << _("Supported modules:") << endl;
3398
3399 for (unsigned I = 0; I != pkgVersioningSystem::GlobalListLen; I++)
3400 {
3401 pkgVersioningSystem *VS = pkgVersioningSystem::GlobalList[I];
3402 if (_system != 0 && _system->VS == VS)
3403 cout << '*';
3404 else
3405 cout << ' ';
3406 cout << "Ver: " << VS->Label << endl;
3407
3408 /* Print out all the packaging systems that will work with
3409 this VS */
3410 for (unsigned J = 0; J != pkgSystem::GlobalListLen; J++)
3411 {
3412 pkgSystem *Sys = pkgSystem::GlobalList[J];
3413 if (_system == Sys)
3414 cout << '*';
3415 else
3416 cout << ' ';
3417 if (Sys->VS->TestCompatibility(*VS) == true)
3418 cout << "Pkg: " << Sys->Label << " (Priority " << Sys->Score(*_config) << ")" << endl;
3419 }
3420 }
3421
3422 for (unsigned I = 0; I != pkgSourceList::Type::GlobalListLen; I++)
3423 {
3424 pkgSourceList::Type *Type = pkgSourceList::Type::GlobalList[I];
3425 cout << " S.L: '" << Type->Name << "' " << Type->Label << endl;
3426 }
3427
3428 for (unsigned I = 0; I != pkgIndexFile::Type::GlobalListLen; I++)
3429 {
3430 pkgIndexFile::Type *Type = pkgIndexFile::Type::GlobalList[I];
3431 cout << " Idx: " << Type->Label << endl;
3432 }
3433
3434 return true;
3435 }
3436
3437 cout <<
3438 _("Usage: apt-get [options] command\n"
3439 " apt-get [options] install|remove pkg1 [pkg2 ...]\n"
3440 " apt-get [options] source pkg1 [pkg2 ...]\n"
3441 "\n"
3442 "apt-get is a simple command line interface for downloading and\n"
3443 "installing packages. The most frequently used commands are update\n"
3444 "and install.\n"
3445 "\n"
3446 "Commands:\n"
3447 " update - Retrieve new lists of packages\n"
3448 " upgrade - Perform an upgrade\n"
3449 " install - Install new packages (pkg is libc6 not libc6.deb)\n"
3450 " remove - Remove packages\n"
3451 " autoremove - Remove automatically all unused packages\n"
3452 " purge - Remove packages and config files\n"
3453 " source - Download source archives\n"
3454 " build-dep - Configure build-dependencies for source packages\n"
3455 " dist-upgrade - Distribution upgrade, see apt-get(8)\n"
3456 " dselect-upgrade - Follow dselect selections\n"
3457 " clean - Erase downloaded archive files\n"
3458 " autoclean - Erase old downloaded archive files\n"
3459 " check - Verify that there are no broken dependencies\n"
3460 " changelog - Download and display the changelog for the given package\n"
3461 " download - Download the binary package into the current directory\n"
3462 "\n"
3463 "Options:\n"
3464 " -h This help text.\n"
3465 " -q Loggable output - no progress indicator\n"
3466 " -qq No output except for errors\n"
3467 " -d Download only - do NOT install or unpack archives\n"
3468 " -s No-act. Perform ordering simulation\n"
3469 " -y Assume Yes to all queries and do not prompt\n"
3470 " -f Attempt to correct a system with broken dependencies in place\n"
3471 " -m Attempt to continue if archives are unlocatable\n"
3472 " -u Show a list of upgraded packages as well\n"
3473 " -b Build the source package after fetching it\n"
3474 " -V Show verbose version numbers\n"
3475 " -c=? Read this configuration file\n"
3476 " -o=? Set an arbitrary configuration option, eg -o dir::cache=/tmp\n"
3477 "See the apt-get(8), sources.list(5) and apt.conf(5) manual\n"
3478 "pages for more information and options.\n"
3479 " This APT has Super Cow Powers.\n");
3480 return true;
3481 }
3482 /*}}}*/
3483 // SigWinch - Window size change signal handler /*{{{*/
3484 // ---------------------------------------------------------------------
3485 /* */
3486 void SigWinch(int)
3487 {
3488 // Riped from GNU ls
3489 #ifdef TIOCGWINSZ
3490 struct winsize ws;
3491
3492 if (ioctl(1, TIOCGWINSZ, &ws) != -1 && ws.ws_col >= 5)
3493 ScreenWidth = ws.ws_col - 1;
3494 #endif
3495 }
3496 /*}}}*/
3497 int main(int argc,const char *argv[]) /*{{{*/
3498 {
3499 CommandLine::Args Args[] = {
3500 {'h',"help","help",0},
3501 {'v',"version","version",0},
3502 {'V',"verbose-versions","APT::Get::Show-Versions",0},
3503 {'q',"quiet","quiet",CommandLine::IntLevel},
3504 {'q',"silent","quiet",CommandLine::IntLevel},
3505 {'d',"download-only","APT::Get::Download-Only",0},
3506 {'b',"compile","APT::Get::Compile",0},
3507 {'b',"build","APT::Get::Compile",0},
3508 {'s',"simulate","APT::Get::Simulate",0},
3509 {'s',"just-print","APT::Get::Simulate",0},
3510 {'s',"recon","APT::Get::Simulate",0},
3511 {'s',"dry-run","APT::Get::Simulate",0},
3512 {'s',"no-act","APT::Get::Simulate",0},
3513 {'y',"yes","APT::Get::Assume-Yes",0},
3514 {'y',"assume-yes","APT::Get::Assume-Yes",0},
3515 {0,"assume-no","APT::Get::Assume-No",0},
3516 {'f',"fix-broken","APT::Get::Fix-Broken",0},
3517 {'u',"show-upgraded","APT::Get::Show-Upgraded",0},
3518 {'m',"ignore-missing","APT::Get::Fix-Missing",0},
3519 {'t',"target-release","APT::Default-Release",CommandLine::HasArg},
3520 {'t',"default-release","APT::Default-Release",CommandLine::HasArg},
3521 {'a',"host-architecture","APT::Get::Host-Architecture",CommandLine::HasArg},
3522 {0,"download","APT::Get::Download",0},
3523 {0,"fix-missing","APT::Get::Fix-Missing",0},
3524 {0,"ignore-hold","APT::Ignore-Hold",0},
3525 {0,"upgrade","APT::Get::upgrade",0},
3526 {0,"only-upgrade","APT::Get::Only-Upgrade",0},
3527 {0,"force-yes","APT::Get::force-yes",0},
3528 {0,"print-uris","APT::Get::Print-URIs",0},
3529 {0,"diff-only","APT::Get::Diff-Only",0},
3530 {0,"debian-only","APT::Get::Diff-Only",0},
3531 {0,"tar-only","APT::Get::Tar-Only",0},
3532 {0,"dsc-only","APT::Get::Dsc-Only",0},
3533 {0,"purge","APT::Get::Purge",0},
3534 {0,"list-cleanup","APT::Get::List-Cleanup",0},
3535 {0,"reinstall","APT::Get::ReInstall",0},
3536 {0,"trivial-only","APT::Get::Trivial-Only",0},
3537 {0,"remove","APT::Get::Remove",0},
3538 {0,"only-source","APT::Get::Only-Source",0},
3539 {0,"arch-only","APT::Get::Arch-Only",0},
3540 {0,"auto-remove","APT::Get::AutomaticRemove",0},
3541 {0,"allow-unauthenticated","APT::Get::AllowUnauthenticated",0},
3542 {0,"install-recommends","APT::Install-Recommends",CommandLine::Boolean},
3543 {0,"install-suggests","APT::Install-Suggests",CommandLine::Boolean},
3544 {0,"fix-policy","APT::Get::Fix-Policy-Broken",0},
3545 {0,"solver","APT::Solver",CommandLine::HasArg},
3546 {'c',"config-file",0,CommandLine::ConfigFile},
3547 {'o',"option",0,CommandLine::ArbItem},
3548 {0,0,0,0}};
3549 CommandLine::Dispatch Cmds[] = {{"update",&DoUpdate},
3550 {"upgrade",&DoUpgrade},
3551 {"install",&DoInstall},
3552 {"remove",&DoInstall},
3553 {"purge",&DoInstall},
3554 {"autoremove",&DoInstall},
3555 {"markauto",&DoMarkAuto},
3556 {"unmarkauto",&DoMarkAuto},
3557 {"dist-upgrade",&DoDistUpgrade},
3558 {"dselect-upgrade",&DoDSelectUpgrade},
3559 {"build-dep",&DoBuildDep},
3560 {"clean",&DoClean},
3561 {"autoclean",&DoAutoClean},
3562 {"check",&DoCheck},
3563 {"source",&DoSource},
3564 {"download",&DoDownload},
3565 {"changelog",&DoChangelog},
3566 {"moo",&DoMoo},
3567 {"help",&ShowHelp},
3568 {0,0}};
3569
3570 // Set up gettext support
3571 setlocale(LC_ALL,"");
3572 textdomain(PACKAGE);
3573
3574 // Parse the command line and initialize the package library
3575 CommandLine CmdL(Args,_config);
3576 if (pkgInitConfig(*_config) == false ||
3577 CmdL.Parse(argc,argv) == false ||
3578 pkgInitSystem(*_config,_system) == false)
3579 {
3580 if (_config->FindB("version") == true)
3581 ShowHelp(CmdL);
3582
3583 _error->DumpErrors();
3584 return 100;
3585 }
3586
3587 // See if the help should be shown
3588 if (_config->FindB("help") == true ||
3589 _config->FindB("version") == true ||
3590 CmdL.FileSize() == 0)
3591 {
3592 ShowHelp(CmdL);
3593 return 0;
3594 }
3595
3596 // simulate user-friendly if apt-get has no root privileges
3597 if (getuid() != 0 && _config->FindB("APT::Get::Simulate") == true &&
3598 (CmdL.FileSize() == 0 ||
3599 (strcmp(CmdL.FileList[0], "source") != 0 && strcmp(CmdL.FileList[0], "download") != 0 &&
3600 strcmp(CmdL.FileList[0], "changelog") != 0)))
3601 {
3602 if (_config->FindB("APT::Get::Show-User-Simulation-Note",true) == true)
3603 cout << _("NOTE: This is only a simulation!\n"
3604 " apt-get needs root privileges for real execution.\n"
3605 " Keep also in mind that locking is deactivated,\n"
3606 " so don't depend on the relevance to the real current situation!"
3607 ) << std::endl;
3608 _config->Set("Debug::NoLocking",true);
3609 }
3610
3611 // Deal with stdout not being a tty
3612 if (!isatty(STDOUT_FILENO) && _config->FindI("quiet", -1) == -1)
3613 _config->Set("quiet","1");
3614
3615 // Setup the output streams
3616 c0out.rdbuf(cout.rdbuf());
3617 c1out.rdbuf(cout.rdbuf());
3618 c2out.rdbuf(cout.rdbuf());
3619 if (_config->FindI("quiet",0) > 0)
3620 c0out.rdbuf(devnull.rdbuf());
3621 if (_config->FindI("quiet",0) > 1)
3622 c1out.rdbuf(devnull.rdbuf());
3623
3624 // Setup the signals
3625 signal(SIGPIPE,SIG_IGN);
3626 signal(SIGWINCH,SigWinch);
3627 SigWinch(0);
3628
3629 // Match the operation
3630 CmdL.DispatchArg(Cmds);
3631
3632 // Print any errors or warnings found during parsing
3633 bool const Errors = _error->PendingError();
3634 if (_config->FindI("quiet",0) > 0)
3635 _error->DumpErrors();
3636 else
3637 _error->DumpErrors(GlobalError::DEBUG);
3638 return Errors == true ? 100 : 0;
3639 }
3640 /*}}}*/