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