]> git.saurik.com Git - apt-legacy.git/blob - cmdline/apt-get.cc
I am sick of that Package: error.
[apt-legacy.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 <apt-pkg/error.h>
29 #include <apt-pkg/cmndline.h>
30 #include <apt-pkg/init.h>
31 #include <apt-pkg/depcache.h>
32 #include <apt-pkg/sourcelist.h>
33 #include <apt-pkg/algorithms.h>
34 #include <apt-pkg/acquire-item.h>
35 #include <apt-pkg/strutl.h>
36 #include <apt-pkg/clean.h>
37 #include <apt-pkg/srcrecords.h>
38 #include <apt-pkg/version.h>
39 #include <apt-pkg/cachefile.h>
40 #include <apt-pkg/sptr.h>
41 #include <apt-pkg/md5.h>
42 #include <apt-pkg/versionmatch.h>
43
44 #include <config.h>
45 #include <apti18n.h>
46
47 #include "acqprogress.h"
48
49 #include <set>
50 #include <locale.h>
51 #include <langinfo.h>
52 #include <fstream>
53 #include <termios.h>
54 #include <sys/ioctl.h>
55 #include <sys/stat.h>
56 #include <sys/param.h>
57 #include <sys/mount.h>
58 #include <sys/statvfs.h>
59 #include <signal.h>
60 #include <unistd.h>
61 #include <stdio.h>
62 #include <errno.h>
63 #include <regex.h>
64 #include <sys/wait.h>
65 #include <sstream>
66 /*}}}*/
67
68 #define RAMFS_MAGIC 0x858458f6
69
70 #define _trace() printf("_trace(%s:%d)\n", __FILE__, __LINE__)
71
72 using namespace std;
73
74 ostream c0out(0);
75 ostream c1out(0);
76 ostream c2out(0);
77 unsigned int ScreenWidth = 80 - 1; /* - 1 for the cursor */
78
79 // class CacheFile - Cover class for some dependency cache functions /*{{{*/
80 // ---------------------------------------------------------------------
81 /* */
82 class CacheFile : public pkgCacheFile
83 {
84 static pkgCache *SortCache;
85 static int NameComp(const void *a,const void *b);
86
87 public:
88 pkgCache::Package **List;
89
90 void Sort();
91 bool CheckDeps(bool AllowBroken = false);
92 bool BuildCaches(bool WithLock = true)
93 {
94 OpTextProgress Prog(*_config);
95 if (pkgCacheFile::BuildCaches(Prog,WithLock) == false)
96 return false;
97 return true;
98 }
99 bool Open(bool WithLock = true)
100 {
101 OpTextProgress Prog(*_config);
102 if (pkgCacheFile::Open(Prog,WithLock) == false)
103 return false;
104 Sort();
105
106 return true;
107 };
108 bool OpenForInstall()
109 {
110 if (_config->FindB("APT::Get::Print-URIs") == true)
111 return Open(false);
112 else
113 return Open(true);
114 }
115 CacheFile() : List(0) {};
116 };
117 /*}}}*/
118
119 // YnPrompt - Yes No Prompt. /*{{{*/
120 // ---------------------------------------------------------------------
121 /* Returns true on a Yes.*/
122 bool YnPrompt(bool Default=true)
123 {
124 if (_config->FindB("APT::Get::Assume-Yes",false) == true)
125 {
126 c1out << _("Y") << endl;
127 return true;
128 }
129
130 char response[1024] = "";
131 cin.getline(response, sizeof(response));
132
133 if (!cin)
134 return false;
135
136 if (strlen(response) == 0)
137 return Default;
138
139 regex_t Pattern;
140 int Res;
141
142 Res = regcomp(&Pattern, nl_langinfo(YESEXPR),
143 REG_EXTENDED|REG_ICASE|REG_NOSUB);
144
145 if (Res != 0) {
146 char Error[300];
147 regerror(Res,&Pattern,Error,sizeof(Error));
148 return _error->Error(_("Regex compilation error - %s"),Error);
149 }
150
151 Res = regexec(&Pattern, response, 0, NULL, 0);
152 if (Res == 0)
153 return true;
154 return false;
155 }
156 /*}}}*/
157 // AnalPrompt - Annoying Yes No Prompt. /*{{{*/
158 // ---------------------------------------------------------------------
159 /* Returns true on a Yes.*/
160 bool AnalPrompt(const char *Text)
161 {
162 char Buf[1024];
163 cin.getline(Buf,sizeof(Buf));
164 if (strcmp(Buf,Text) == 0)
165 return true;
166 return false;
167 }
168 /*}}}*/
169 // ShowList - Show a list /*{{{*/
170 // ---------------------------------------------------------------------
171 /* This prints out a string of space separated words with a title and
172 a two space indent line wraped to the current screen width. */
173 bool ShowList(ostream &out,string Title,string List,string VersionsList)
174 {
175 if (List.empty() == true)
176 return true;
177 // trim trailing space
178 int NonSpace = List.find_last_not_of(' ');
179 if (NonSpace != -1)
180 {
181 List = List.erase(NonSpace + 1);
182 if (List.empty() == true)
183 return true;
184 }
185
186 // Acount for the leading space
187 int ScreenWidth = ::ScreenWidth - 3;
188
189 out << Title << endl;
190 string::size_type Start = 0;
191 string::size_type VersionsStart = 0;
192 while (Start < List.size())
193 {
194 if(_config->FindB("APT::Get::Show-Versions",false) == true &&
195 VersionsList.size() > 0) {
196 string::size_type End;
197 string::size_type VersionsEnd;
198
199 End = List.find(' ',Start);
200 VersionsEnd = VersionsList.find('\n', VersionsStart);
201
202 out << " " << string(List,Start,End - Start) << " (" <<
203 string(VersionsList,VersionsStart,VersionsEnd - VersionsStart) <<
204 ")" << endl;
205
206 if (End == string::npos || End < Start)
207 End = Start + ScreenWidth;
208
209 Start = End + 1;
210 VersionsStart = VersionsEnd + 1;
211 } else {
212 string::size_type End;
213
214 if (Start + ScreenWidth >= List.size())
215 End = List.size();
216 else
217 End = List.rfind(' ',Start+ScreenWidth);
218
219 if (End == string::npos || End < Start)
220 End = Start + ScreenWidth;
221 out << " " << string(List,Start,End - Start) << endl;
222 Start = End + 1;
223 }
224 }
225
226 return false;
227 }
228 /*}}}*/
229 // ShowBroken - Debugging aide /*{{{*/
230 // ---------------------------------------------------------------------
231 /* This prints out the names of all the packages that are broken along
232 with the name of each each broken dependency and a quite version
233 description.
234
235 The output looks like:
236 The following packages have unmet dependencies:
237 exim: Depends: libc6 (>= 2.1.94) but 2.1.3-10 is to be installed
238 Depends: libldap2 (>= 2.0.2-2) but it is not going to be installed
239 Depends: libsasl7 but it is not going to be installed
240 */
241 void ShowBroken(ostream &out,CacheFile &Cache,bool Now)
242 {
243 out << _("The following packages have unmet dependencies:") << endl;
244 for (unsigned J = 0; J < Cache->Head().PackageCount; J++)
245 {
246 pkgCache::PkgIterator I(Cache,Cache.List[J]);
247
248 if (Now == true)
249 {
250 if (Cache[I].NowBroken() == false)
251 continue;
252 }
253 else
254 {
255 if (Cache[I].InstBroken() == false)
256 continue;
257 }
258
259 // Print out each package and the failed dependencies
260 out <<" " << I.Name() << ":";
261 unsigned Indent = strlen(I.Name()) + 3;
262 bool First = true;
263 pkgCache::VerIterator Ver;
264
265 if (Now == true)
266 Ver = I.CurrentVer();
267 else
268 Ver = Cache[I].InstVerIter(Cache);
269
270 if (Ver.end() == true)
271 {
272 out << endl;
273 continue;
274 }
275
276 for (pkgCache::DepIterator D = Ver.DependsList(); D.end() == false;)
277 {
278 // Compute a single dependency element (glob or)
279 pkgCache::DepIterator Start;
280 pkgCache::DepIterator End;
281 D.GlobOr(Start,End); // advances D
282
283 if (Cache->IsImportantDep(End) == false)
284 continue;
285
286 if (Now == true)
287 {
288 if ((Cache[End] & pkgDepCache::DepGNow) == pkgDepCache::DepGNow)
289 continue;
290 }
291 else
292 {
293 if ((Cache[End] & pkgDepCache::DepGInstall) == pkgDepCache::DepGInstall)
294 continue;
295 }
296
297 bool FirstOr = true;
298 while (1)
299 {
300 if (First == false)
301 for (unsigned J = 0; J != Indent; J++)
302 out << ' ';
303 First = false;
304
305 if (FirstOr == false)
306 {
307 for (unsigned J = 0; J != strlen(End.DepType()) + 3; J++)
308 out << ' ';
309 }
310 else
311 out << ' ' << End.DepType() << ": ";
312 FirstOr = false;
313
314 out << Start.TargetPkg().Name();
315
316 // Show a quick summary of the version requirements
317 if (Start.TargetVer() != 0)
318 out << " (" << Start.CompType() << " " << Start.TargetVer() << ")";
319
320 /* Show a summary of the target package if possible. In the case
321 of virtual packages we show nothing */
322 pkgCache::PkgIterator Targ = Start.TargetPkg();
323 if (Targ->ProvidesList == 0)
324 {
325 out << ' ';
326 pkgCache::VerIterator Ver = Cache[Targ].InstVerIter(Cache);
327 if (Now == true)
328 Ver = Targ.CurrentVer();
329
330 if (Ver.end() == false)
331 {
332 if (Now == true)
333 ioprintf(out,_("but %s is installed"),Ver.VerStr());
334 else
335 ioprintf(out,_("but %s is to be installed"),Ver.VerStr());
336 }
337 else
338 {
339 if (Cache[Targ].CandidateVerIter(Cache).end() == true)
340 {
341 if (Targ->ProvidesList == 0)
342 out << _("but it is not installable");
343 else
344 out << _("but it is a virtual package");
345 }
346 else
347 out << (Now?_("but it is not installed"):_("but it is not going to be installed"));
348 }
349 }
350
351 if (Start != End)
352 out << _(" or");
353 out << endl;
354
355 if (Start == End)
356 break;
357 Start++;
358 }
359 }
360 }
361 }
362 /*}}}*/
363 // ShowNew - Show packages to newly install /*{{{*/
364 // ---------------------------------------------------------------------
365 /* */
366 void ShowNew(ostream &out,CacheFile &Cache)
367 {
368 /* Print out a list of packages that are going to be installed extra
369 to what the user asked */
370 string List;
371 string VersionsList;
372 for (unsigned J = 0; J < Cache->Head().PackageCount; J++)
373 {
374 pkgCache::PkgIterator I(Cache,Cache.List[J]);
375 if (Cache[I].NewInstall() == true) {
376 List += string(I.Name()) + " ";
377 VersionsList += string(Cache[I].CandVersion) + "\n";
378 }
379 }
380
381 ShowList(out,_("The following NEW packages will be installed:"),List,VersionsList);
382 }
383 /*}}}*/
384 // ShowDel - Show packages to delete /*{{{*/
385 // ---------------------------------------------------------------------
386 /* */
387 void ShowDel(ostream &out,CacheFile &Cache)
388 {
389 /* Print out a list of packages that are going to be removed extra
390 to what the user asked */
391 string List;
392 string VersionsList;
393 for (unsigned J = 0; J < Cache->Head().PackageCount; J++)
394 {
395 pkgCache::PkgIterator I(Cache,Cache.List[J]);
396 if (Cache[I].Delete() == true)
397 {
398 if ((Cache[I].iFlags & pkgDepCache::Purge) == pkgDepCache::Purge)
399 List += string(I.Name()) + "* ";
400 else
401 List += string(I.Name()) + " ";
402
403 VersionsList += string(Cache[I].CandVersion)+ "\n";
404 }
405 }
406
407 ShowList(out,_("The following packages will be REMOVED:"),List,VersionsList);
408 }
409 /*}}}*/
410 // ShowKept - Show kept packages /*{{{*/
411 // ---------------------------------------------------------------------
412 /* */
413 void ShowKept(ostream &out,CacheFile &Cache)
414 {
415 string List;
416 string VersionsList;
417 for (unsigned J = 0; J < Cache->Head().PackageCount; J++)
418 {
419 pkgCache::PkgIterator I(Cache,Cache.List[J]);
420
421 // Not interesting
422 if (Cache[I].Upgrade() == true || Cache[I].Upgradable() == false ||
423 I->CurrentVer == 0 || Cache[I].Delete() == true)
424 continue;
425
426 List += string(I.Name()) + " ";
427 VersionsList += string(Cache[I].CurVersion) + " => " + Cache[I].CandVersion + "\n";
428 }
429 ShowList(out,_("The following packages have been kept back:"),List,VersionsList);
430 }
431 /*}}}*/
432 // ShowUpgraded - Show upgraded packages /*{{{*/
433 // ---------------------------------------------------------------------
434 /* */
435 void ShowUpgraded(ostream &out,CacheFile &Cache)
436 {
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
443 // Not interesting
444 if (Cache[I].Upgrade() == false || Cache[I].NewInstall() == true)
445 continue;
446
447 List += string(I.Name()) + " ";
448 VersionsList += string(Cache[I].CurVersion) + " => " + Cache[I].CandVersion + "\n";
449 }
450 ShowList(out,_("The following packages will be upgraded:"),List,VersionsList);
451 }
452 /*}}}*/
453 // ShowDowngraded - Show downgraded packages /*{{{*/
454 // ---------------------------------------------------------------------
455 /* */
456 bool ShowDowngraded(ostream &out,CacheFile &Cache)
457 {
458 string List;
459 string VersionsList;
460 for (unsigned J = 0; J < Cache->Head().PackageCount; J++)
461 {
462 pkgCache::PkgIterator I(Cache,Cache.List[J]);
463
464 // Not interesting
465 if (Cache[I].Downgrade() == false || Cache[I].NewInstall() == true)
466 continue;
467
468 List += string(I.Name()) + " ";
469 VersionsList += string(Cache[I].CurVersion) + " => " + Cache[I].CandVersion + "\n";
470 }
471 return ShowList(out,_("The following packages will be DOWNGRADED:"),List,VersionsList);
472 }
473 /*}}}*/
474 // ShowHold - Show held but changed packages /*{{{*/
475 // ---------------------------------------------------------------------
476 /* */
477 bool ShowHold(ostream &out,CacheFile &Cache)
478 {
479 string List;
480 string VersionsList;
481 for (unsigned J = 0; J < Cache->Head().PackageCount; J++)
482 {
483 pkgCache::PkgIterator I(Cache,Cache.List[J]);
484 if (Cache[I].InstallVer != (pkgCache::Version *)I.CurrentVer() &&
485 I->SelectedState == pkgCache::State::Hold) {
486 List += string(I.Name()) + " ";
487 VersionsList += string(Cache[I].CurVersion) + " => " + Cache[I].CandVersion + "\n";
488 }
489 }
490
491 return ShowList(out,_("The following held packages will be changed:"),List,VersionsList);
492 }
493 /*}}}*/
494 // ShowEssential - Show an essential package warning /*{{{*/
495 // ---------------------------------------------------------------------
496 /* This prints out a warning message that is not to be ignored. It shows
497 all essential packages and their dependents that are to be removed.
498 It is insanely risky to remove the dependents of an essential package! */
499 bool ShowEssential(ostream &out,CacheFile &Cache)
500 {
501 string List;
502 string VersionsList;
503 bool *Added = new bool[Cache->Head().PackageCount];
504 for (unsigned int I = 0; I != Cache->Head().PackageCount; I++)
505 Added[I] = false;
506
507 for (unsigned J = 0; J < Cache->Head().PackageCount; J++)
508 {
509 pkgCache::PkgIterator I(Cache,Cache.List[J]);
510 if ((I->Flags & pkgCache::Flag::Essential) != pkgCache::Flag::Essential &&
511 (I->Flags & pkgCache::Flag::Important) != pkgCache::Flag::Important)
512 continue;
513
514 // The essential package is being removed
515 if (Cache[I].Delete() == true)
516 {
517 if (Added[I->ID] == false)
518 {
519 Added[I->ID] = true;
520 List += string(I.Name()) + " ";
521 //VersionsList += string(Cache[I].CurVersion) + "\n"; ???
522 }
523 }
524
525 if (I->CurrentVer == 0)
526 continue;
527
528 // Print out any essential package depenendents that are to be removed
529 for (pkgCache::DepIterator D = I.CurrentVer().DependsList(); D.end() == false; D++)
530 {
531 // Skip everything but depends
532 if (D->Type != pkgCache::Dep::PreDepends &&
533 D->Type != pkgCache::Dep::Depends)
534 continue;
535
536 pkgCache::PkgIterator P = D.SmartTargetPkg();
537 if (Cache[P].Delete() == true)
538 {
539 if (Added[P->ID] == true)
540 continue;
541 Added[P->ID] = true;
542
543 char S[300];
544 snprintf(S,sizeof(S),_("%s (due to %s) "),P.Name(),I.Name());
545 List += S;
546 //VersionsList += "\n"; ???
547 }
548 }
549 }
550
551 delete [] Added;
552 return ShowList(out,_("WARNING: The following essential packages will be removed.\n"
553 "This should NOT be done unless you know exactly what you are doing!"),List,VersionsList);
554 }
555
556 /*}}}*/
557 // Stats - Show some statistics /*{{{*/
558 // ---------------------------------------------------------------------
559 /* */
560 void Stats(ostream &out,pkgDepCache &Dep)
561 {
562 unsigned long Upgrade = 0;
563 unsigned long Downgrade = 0;
564 unsigned long Install = 0;
565 unsigned long ReInstall = 0;
566 for (pkgCache::PkgIterator I = Dep.PkgBegin(); I.end() == false; I++)
567 {
568 if (Dep[I].NewInstall() == true)
569 Install++;
570 else
571 {
572 if (Dep[I].Upgrade() == true)
573 Upgrade++;
574 else
575 if (Dep[I].Downgrade() == true)
576 Downgrade++;
577 }
578
579 if (Dep[I].Delete() == false && (Dep[I].iFlags & pkgDepCache::ReInstall) == pkgDepCache::ReInstall)
580 ReInstall++;
581 }
582
583 ioprintf(out,_("%lu upgraded, %lu newly installed, "),
584 Upgrade,Install);
585
586 if (ReInstall != 0)
587 ioprintf(out,_("%lu reinstalled, "),ReInstall);
588 if (Downgrade != 0)
589 ioprintf(out,_("%lu downgraded, "),Downgrade);
590
591 ioprintf(out,_("%lu to remove and %lu not upgraded.\n"),
592 Dep.DelCount(),Dep.KeepCount());
593
594 if (Dep.BadCount() != 0)
595 ioprintf(out,_("%lu not fully installed or removed.\n"),
596 Dep.BadCount());
597 }
598 /*}}}*/
599
600 // CacheFile::NameComp - QSort compare by name /*{{{*/
601 // ---------------------------------------------------------------------
602 /* */
603 pkgCache *CacheFile::SortCache = 0;
604 int CacheFile::NameComp(const void *a,const void *b)
605 {
606 if (*(pkgCache::Package **)a == 0 || *(pkgCache::Package **)b == 0)
607 return *(pkgCache::Package **)a - *(pkgCache::Package **)b;
608
609 const pkgCache::Package &A = **(pkgCache::Package **)a;
610 const pkgCache::Package &B = **(pkgCache::Package **)b;
611
612 return strcmp(SortCache->StrP + A.Name,SortCache->StrP + B.Name);
613 }
614 /*}}}*/
615 // CacheFile::Sort - Sort by name /*{{{*/
616 // ---------------------------------------------------------------------
617 /* */
618 void CacheFile::Sort()
619 {
620 delete [] List;
621 List = new pkgCache::Package *[Cache->Head().PackageCount];
622 memset(List,0,sizeof(*List)*Cache->Head().PackageCount);
623 pkgCache::PkgIterator I = Cache->PkgBegin();
624 for (;I.end() != true; I++)
625 List[I->ID] = I;
626
627 SortCache = *this;
628 qsort(List,Cache->Head().PackageCount,sizeof(*List),NameComp);
629 }
630 /*}}}*/
631 // CacheFile::CheckDeps - Open the cache file /*{{{*/
632 // ---------------------------------------------------------------------
633 /* This routine generates the caches and then opens the dependency cache
634 and verifies that the system is OK. */
635 bool CacheFile::CheckDeps(bool AllowBroken)
636 {
637 bool FixBroken = _config->FindB("APT::Get::Fix-Broken",false);
638
639 if (_error->PendingError() == true)
640 return false;
641
642 // Check that the system is OK
643 if (DCache->DelCount() != 0 || DCache->InstCount() != 0)
644 return _error->Error("Internal error, non-zero counts");
645
646 // Apply corrections for half-installed packages
647 if (pkgApplyStatus(*DCache) == false)
648 return false;
649
650 if (_config->FindB("APT::Get::Fix-Policy-Broken",false) == true)
651 {
652 FixBroken = true;
653 if ((DCache->PolicyBrokenCount() > 0))
654 {
655 // upgrade all policy-broken packages with ForceImportantDeps=True
656 for (pkgCache::PkgIterator I = Cache->PkgBegin(); !I.end(); I++)
657 if ((*DCache)[I].NowPolicyBroken() == true)
658 DCache->MarkInstall(I,true,0, false, true);
659 }
660 }
661
662 // Nothing is broken
663 if (DCache->BrokenCount() == 0 || AllowBroken == true)
664 return true;
665
666 // Attempt to fix broken things
667 if (FixBroken == true)
668 {
669 c1out << _("Correcting dependencies...") << flush;
670 if (pkgFixBroken(*DCache) == false || DCache->BrokenCount() != 0)
671 {
672 c1out << _(" failed.") << endl;
673 ShowBroken(c1out,*this,true);
674
675 return _error->Error(_("Unable to correct dependencies"));
676 }
677 if (pkgMinimizeUpgrade(*DCache) == false)
678 return _error->Error(_("Unable to minimize the upgrade set"));
679
680 c1out << _(" Done") << endl;
681 }
682 else
683 {
684 c1out << _("You might want to run `apt-get -f install' to correct these.") << endl;
685 ShowBroken(c1out,*this,true);
686
687 return _error->Error(_("Unmet dependencies. Try using -f."));
688 }
689
690 return true;
691 }
692
693 static bool CheckAuth(pkgAcquire& Fetcher)
694 {
695 string UntrustedList;
696 for (pkgAcquire::ItemIterator I = Fetcher.ItemsBegin(); I < Fetcher.ItemsEnd(); ++I)
697 {
698 if (!(*I)->IsTrusted())
699 {
700 UntrustedList += string((*I)->ShortDesc()) + " ";
701 }
702 }
703
704 if (UntrustedList == "")
705 {
706 return true;
707 }
708
709 ShowList(c2out,_("WARNING: The following packages cannot be authenticated!"),UntrustedList,"");
710
711 if (_config->FindB("APT::Get::AllowUnauthenticated",false) == true)
712 {
713 c2out << _("Authentication warning overridden.\n");
714 return true;
715 }
716
717 if (_config->FindI("quiet",0) < 2
718 && _config->FindB("APT::Get::Assume-Yes",false) == false)
719 {
720 c2out << _("Install these packages without verification [y/N]? ") << flush;
721 if (!YnPrompt(false))
722 return _error->Error(_("Some packages could not be authenticated"));
723
724 return true;
725 }
726 else if (_config->FindB("APT::Get::Force-Yes",false) == true)
727 {
728 return true;
729 }
730
731 return _error->Error(_("There are problems and -y was used without --force-yes"));
732 }
733
734
735 /*}}}*/
736
737 // InstallPackages - Actually download and install the packages /*{{{*/
738 // ---------------------------------------------------------------------
739 /* This displays the informative messages describing what is going to
740 happen and then calls the download routines */
741 bool InstallPackages(CacheFile &Cache,bool ShwKept,bool Ask = true,
742 bool Safety = true)
743 {
744 if (_config->FindB("APT::Get::Purge",false) == true)
745 {
746 pkgCache::PkgIterator I = Cache->PkgBegin();
747 for (; I.end() == false; I++)
748 {
749 if (I.Purge() == false && Cache[I].Mode == pkgDepCache::ModeDelete)
750 Cache->MarkDelete(I,true);
751 }
752 }
753
754 bool Fail = false;
755 bool Essential = false;
756
757 // Show all the various warning indicators
758 ShowDel(c1out,Cache);
759 ShowNew(c1out,Cache);
760 if (ShwKept == true)
761 ShowKept(c1out,Cache);
762 Fail |= !ShowHold(c1out,Cache);
763 if (_config->FindB("APT::Get::Show-Upgraded",true) == true)
764 ShowUpgraded(c1out,Cache);
765 Fail |= !ShowDowngraded(c1out,Cache);
766 if (_config->FindB("APT::Get::Download-Only",false) == false)
767 Essential = !ShowEssential(c1out,Cache);
768 Fail |= Essential;
769 Stats(c1out,Cache);
770
771 // Sanity check
772 if (Cache->BrokenCount() != 0)
773 {
774 ShowBroken(c1out,Cache,false);
775 return _error->Error(_("Internal error, InstallPackages was called with broken packages!"));
776 }
777
778 if (Cache->DelCount() == 0 && Cache->InstCount() == 0 &&
779 Cache->BadCount() == 0)
780 return true;
781
782 // No remove flag
783 if (Cache->DelCount() != 0 && _config->FindB("APT::Get::Remove",true) == false)
784 return _error->Error(_("Packages need to be removed but remove is disabled."));
785
786 // Run the simulator ..
787 if (_config->FindB("APT::Get::Simulate") == true)
788 {
789 pkgSimulate PM(Cache);
790 int status_fd = _config->FindI("APT::Status-Fd",-1);
791 pkgPackageManager::OrderResult Res = PM.DoInstall(status_fd);
792 if (Res == pkgPackageManager::Failed)
793 return false;
794 if (Res != pkgPackageManager::Completed)
795 return _error->Error(_("Internal error, Ordering didn't finish"));
796 return true;
797 }
798
799 // Create the text record parser
800 pkgRecords Recs(Cache);
801 if (_error->PendingError() == true)
802 return false;
803
804 // Lock the archive directory
805 FileFd Lock;
806 if (_config->FindB("Debug::NoLocking",false) == false &&
807 _config->FindB("APT::Get::Print-URIs") == false)
808 {
809 Lock.Fd(GetLock(_config->FindDir("Dir::Cache::Archives") + "lock"));
810 if (_error->PendingError() == true)
811 return _error->Error(_("Unable to lock the download directory"));
812 }
813
814 // Create the download object
815 AcqTextStatus Stat(ScreenWidth,_config->FindI("quiet",0));
816 pkgAcquire Fetcher(&Stat);
817
818 // Read the source list
819 pkgSourceList List;
820 if (List.ReadMainList() == false)
821 return _error->Error(_("The list of sources could not be read."));
822
823 // Create the package manager and prepare to download
824 SPtr<pkgPackageManager> PM= _system->CreatePM(Cache);
825 if (PM->GetArchives(&Fetcher,&List,&Recs) == false ||
826 _error->PendingError() == true)
827 return false;
828
829 // Display statistics
830 double FetchBytes = Fetcher.FetchNeeded();
831 double FetchPBytes = Fetcher.PartialPresent();
832 double DebBytes = Fetcher.TotalNeeded();
833 if (DebBytes != Cache->DebSize())
834 {
835 c0out << DebBytes << ',' << Cache->DebSize() << endl;
836 c0out << _("How odd.. The sizes didn't match, email apt@packages.debian.org") << endl;
837 }
838
839 // Number of bytes
840 if (DebBytes != FetchBytes)
841 ioprintf(c1out,_("Need to get %sB/%sB of archives.\n"),
842 SizeToStr(FetchBytes).c_str(),SizeToStr(DebBytes).c_str());
843 else if (DebBytes != 0)
844 ioprintf(c1out,_("Need to get %sB of archives.\n"),
845 SizeToStr(DebBytes).c_str());
846
847 // Size delta
848 if (Cache->UsrSize() >= 0)
849 ioprintf(c1out,_("After this operation, %sB of additional disk space will be used.\n"),
850 SizeToStr(Cache->UsrSize()).c_str());
851 else
852 ioprintf(c1out,_("After this operation, %sB disk space will be freed.\n"),
853 SizeToStr(-1*Cache->UsrSize()).c_str());
854
855 if (_error->PendingError() == true)
856 return false;
857
858 /* Check for enough free space, but only if we are actually going to
859 download */
860 if (_config->FindB("APT::Get::Print-URIs") == false &&
861 _config->FindB("APT::Get::Download",true) == true)
862 {
863 struct statvfs Buf;
864 string OutputDir = _config->FindDir("Dir::Cache::Archives");
865 if (statvfs(OutputDir.c_str(),&Buf) != 0)
866 return _error->Errno("statvfs",_("Couldn't determine free space in %s"),
867 OutputDir.c_str());
868 if (unsigned(Buf.f_bfree) < (FetchBytes - FetchPBytes)/Buf.f_bsize)
869 {
870 struct statfs Stat;
871 if (statfs(OutputDir.c_str(),&Stat) != 0 ||
872 unsigned(Stat.f_type) != RAMFS_MAGIC)
873 return _error->Error(_("You don't have enough free space in %s."),
874 OutputDir.c_str());
875 }
876 }
877
878 // Fail safe check
879 if (_config->FindI("quiet",0) >= 2 ||
880 _config->FindB("APT::Get::Assume-Yes",false) == true)
881 {
882 if (Fail == true && _config->FindB("APT::Get::Force-Yes",false) == false)
883 return _error->Error(_("There are problems and -y was used without --force-yes"));
884 }
885
886 if (Essential == true && Safety == true)
887 {
888 if (_config->FindB("APT::Get::Trivial-Only",false) == true)
889 return _error->Error(_("Trivial Only specified but this is not a trivial operation."));
890
891 const char *Prompt = _("Yes, do as I say!");
892 ioprintf(c2out,
893 _("You are about to do something potentially harmful.\n"
894 "To continue type in the phrase '%s'\n"
895 " ?] "),Prompt);
896 c2out << flush;
897 if (AnalPrompt(Prompt) == false)
898 {
899 c2out << _("Abort.") << endl;
900 exit(1);
901 }
902 }
903 else
904 {
905 // Prompt to continue
906 if (Ask == true || Fail == true)
907 {
908 if (_config->FindB("APT::Get::Trivial-Only",false) == true)
909 return _error->Error(_("Trivial Only specified but this is not a trivial operation."));
910
911 if (_config->FindI("quiet",0) < 2 &&
912 _config->FindB("APT::Get::Assume-Yes",false) == false)
913 {
914 c2out << _("Do you want to continue [Y/n]? ") << flush;
915
916 if (YnPrompt() == false)
917 {
918 c2out << _("Abort.") << endl;
919 exit(1);
920 }
921 }
922 }
923 }
924
925 // Just print out the uris an exit if the --print-uris flag was used
926 if (_config->FindB("APT::Get::Print-URIs") == true)
927 {
928 pkgAcquire::UriIterator I = Fetcher.UriBegin();
929 for (; I != Fetcher.UriEnd(); I++)
930 cout << '\'' << I->URI << "' " << flNotDir(I->Owner->DestFile) << ' ' <<
931 I->Owner->FileSize << ' ' << I->Owner->HashSum() << endl;
932 return true;
933 }
934
935 if (!CheckAuth(Fetcher))
936 return false;
937
938 /* Unlock the dpkg lock if we are not going to be doing an install
939 after. */
940 if (_config->FindB("APT::Get::Download-Only",false) == true)
941 _system->UnLock();
942
943 // Run it
944 while (1)
945 {
946 bool Transient = false;
947 if (_config->FindB("APT::Get::Download",true) == false)
948 {
949 for (pkgAcquire::ItemIterator I = Fetcher.ItemsBegin(); I < Fetcher.ItemsEnd();)
950 {
951 if ((*I)->Local == true)
952 {
953 I++;
954 continue;
955 }
956
957 // Close the item and check if it was found in cache
958 (*I)->Finished();
959 if ((*I)->Complete == false)
960 Transient = true;
961
962 // Clear it out of the fetch list
963 delete *I;
964 I = Fetcher.ItemsBegin();
965 }
966 }
967
968 if (Fetcher.Run() == pkgAcquire::Failed)
969 return false;
970
971 // Print out errors
972 bool Failed = false;
973 for (pkgAcquire::ItemIterator I = Fetcher.ItemsBegin(); I != Fetcher.ItemsEnd(); I++)
974 {
975 if ((*I)->Status == pkgAcquire::Item::StatDone &&
976 (*I)->Complete == true)
977 continue;
978
979 if ((*I)->Status == pkgAcquire::Item::StatIdle)
980 {
981 Transient = true;
982 // Failed = true;
983 continue;
984 }
985
986 fprintf(stderr,_("Failed to fetch %s %s\n"),(*I)->DescURI().c_str(),
987 (*I)->ErrorText.c_str());
988 Failed = true;
989 }
990
991 /* If we are in no download mode and missing files and there were
992 'failures' then the user must specify -m. Furthermore, there
993 is no such thing as a transient error in no-download mode! */
994 if (Transient == true &&
995 _config->FindB("APT::Get::Download",true) == false)
996 {
997 Transient = false;
998 Failed = true;
999 }
1000
1001 if (_config->FindB("APT::Get::Download-Only",false) == true)
1002 {
1003 if (Failed == true && _config->FindB("APT::Get::Fix-Missing",false) == false)
1004 return _error->Error(_("Some files failed to download"));
1005 c1out << _("Download complete and in download only mode") << endl;
1006 return true;
1007 }
1008
1009 if (Failed == true && _config->FindB("APT::Get::Fix-Missing",false) == false)
1010 {
1011 return _error->Error(_("Unable to fetch some archives, maybe run apt-get update or try with --fix-missing?"));
1012 }
1013
1014 if (Transient == true && Failed == true)
1015 return _error->Error(_("--fix-missing and media swapping is not currently supported"));
1016
1017 // Try to deal with missing package files
1018 if (Failed == true && PM->FixMissing() == false)
1019 {
1020 cerr << _("Unable to correct missing packages.") << endl;
1021 return _error->Error(_("Aborting install."));
1022 }
1023
1024 _system->UnLock();
1025 int status_fd = _config->FindI("APT::Status-Fd",-1);
1026 pkgPackageManager::OrderResult Res = PM->DoInstall(status_fd);
1027 if (Res == pkgPackageManager::Failed || _error->PendingError() == true)
1028 return false;
1029 if (Res == pkgPackageManager::Completed)
1030 return true;
1031
1032 // Reload the fetcher object and loop again for media swapping
1033 Fetcher.Shutdown();
1034 if (PM->GetArchives(&Fetcher,&List,&Recs) == false)
1035 return false;
1036
1037 _system->Lock();
1038 }
1039 }
1040 /*}}}*/
1041 // TryToInstall - Try to install a single package /*{{{*/
1042 // ---------------------------------------------------------------------
1043 /* This used to be inlined in DoInstall, but with the advent of regex package
1044 name matching it was split out.. */
1045 bool TryToInstall(pkgCache::PkgIterator Pkg,pkgDepCache &Cache,
1046 pkgProblemResolver &Fix,bool Remove,bool BrokenFix,
1047 unsigned int &ExpectedInst,bool AllowFail = true)
1048 {
1049 /* This is a pure virtual package and there is a single available
1050 provides */
1051 if (Cache[Pkg].CandidateVer == 0 && Pkg->ProvidesList != 0 &&
1052 Pkg.ProvidesList()->NextProvides == 0)
1053 {
1054 pkgCache::PkgIterator Tmp = Pkg.ProvidesList().OwnerPkg();
1055 ioprintf(c1out,_("Note, selecting %s instead of %s\n"),
1056 Tmp.Name(),Pkg.Name());
1057 Pkg = Tmp;
1058 }
1059
1060 // Handle the no-upgrade case
1061 if (_config->FindB("APT::Get::upgrade",true) == false &&
1062 Pkg->CurrentVer != 0)
1063 {
1064 if (AllowFail == true)
1065 ioprintf(c1out,_("Skipping %s, it is already installed and upgrade is not set.\n"),
1066 Pkg.Name());
1067 return true;
1068 }
1069
1070 // Check if there is something at all to install
1071 pkgDepCache::StateCache &State = Cache[Pkg];
1072 if (Remove == true && Pkg->CurrentVer == 0)
1073 {
1074 Fix.Clear(Pkg);
1075 Fix.Protect(Pkg);
1076 Fix.Remove(Pkg);
1077
1078 /* We want to continue searching for regex hits, so we return false here
1079 otherwise this is not really an error. */
1080 if (AllowFail == false)
1081 return false;
1082
1083 ioprintf(c1out,_("Package %s is not installed, so not removed\n"),Pkg.Name());
1084 return true;
1085 }
1086
1087 if (State.CandidateVer == 0 && Remove == false)
1088 {
1089 if (AllowFail == false)
1090 return false;
1091
1092 if (Pkg->ProvidesList != 0)
1093 {
1094 ioprintf(c1out,_("Package %s is a virtual package provided by:\n"),
1095 Pkg.Name());
1096
1097 pkgCache::PrvIterator I = Pkg.ProvidesList();
1098 for (; I.end() == false; I++)
1099 {
1100 pkgCache::PkgIterator Pkg = I.OwnerPkg();
1101
1102 if (Cache[Pkg].CandidateVerIter(Cache) == I.OwnerVer())
1103 {
1104 if (Cache[Pkg].Install() == true && Cache[Pkg].NewInstall() == false)
1105 c1out << " " << Pkg.Name() << " " << I.OwnerVer().VerStr() <<
1106 _(" [Installed]") << endl;
1107 else
1108 c1out << " " << Pkg.Name() << " " << I.OwnerVer().VerStr() << endl;
1109 }
1110 }
1111 c1out << _("You should explicitly select one to install.") << endl;
1112 }
1113 else
1114 {
1115 ioprintf(c1out,
1116 _("Package %s is not available, but is referred to by another package.\n"
1117 "This may mean that the package is missing, has been obsoleted, or\n"
1118 "is only available from another source\n"),Pkg.Name());
1119
1120 string List;
1121 string VersionsList;
1122 SPtrArray<bool> Seen = new bool[Cache.Head().PackageCount];
1123 memset(Seen,0,Cache.Head().PackageCount*sizeof(*Seen));
1124 pkgCache::DepIterator Dep = Pkg.RevDependsList();
1125 for (; Dep.end() == false; Dep++)
1126 {
1127 if (Dep->Type != pkgCache::Dep::Replaces)
1128 continue;
1129 if (Seen[Dep.ParentPkg()->ID] == true)
1130 continue;
1131 Seen[Dep.ParentPkg()->ID] = true;
1132 List += string(Dep.ParentPkg().Name()) + " ";
1133 //VersionsList += string(Dep.ParentPkg().CurVersion) + "\n"; ???
1134 }
1135 ShowList(c1out,_("However the following packages replace it:"),List,VersionsList);
1136 }
1137
1138 _error->Error(_("Package %s has no installation candidate"),Pkg.Name());
1139 return false;
1140 }
1141
1142 Fix.Clear(Pkg);
1143 Fix.Protect(Pkg);
1144 if (Remove == true)
1145 {
1146 Fix.Remove(Pkg);
1147 Cache.MarkDelete(Pkg,_config->FindB("APT::Get::Purge",false));
1148 return true;
1149 }
1150
1151 // Install it
1152 Cache.MarkInstall(Pkg,false);
1153 if (State.Install() == false)
1154 {
1155 if (_config->FindB("APT::Get::ReInstall",false) == true)
1156 {
1157 if (Pkg->CurrentVer == 0 || Pkg.CurrentVer().Downloadable() == false)
1158 ioprintf(c1out,_("Reinstallation of %s is not possible, it cannot be downloaded.\n"),
1159 Pkg.Name());
1160 else
1161 Cache.SetReInstall(Pkg,true);
1162 }
1163 else
1164 {
1165 if (AllowFail == true)
1166 ioprintf(c1out,_("%s is already the newest version.\n"),
1167 Pkg.Name());
1168 }
1169 }
1170 else
1171 ExpectedInst++;
1172
1173 // Install it with autoinstalling enabled (if we not respect the minial
1174 // required deps or the policy)
1175 if ((State.InstBroken() == true || State.InstPolicyBroken() == true) && BrokenFix == false)
1176 Cache.MarkInstall(Pkg,true);
1177
1178 return true;
1179 }
1180 /*}}}*/
1181 // TryToChangeVer - Try to change a candidate version /*{{{*/
1182 // ---------------------------------------------------------------------
1183 /* */
1184 bool TryToChangeVer(pkgCache::PkgIterator Pkg,pkgDepCache &Cache,
1185 const char *VerTag,bool IsRel)
1186 {
1187 pkgVersionMatch Match(VerTag,(IsRel == true?pkgVersionMatch::Release :
1188 pkgVersionMatch::Version));
1189
1190 pkgCache::VerIterator Ver = Match.Find(Pkg);
1191
1192 if (Ver.end() == true)
1193 {
1194 if (IsRel == true)
1195 return _error->Error(_("Release '%s' for '%s' was not found"),
1196 VerTag,Pkg.Name());
1197 return _error->Error(_("Version '%s' for '%s' was not found"),
1198 VerTag,Pkg.Name());
1199 }
1200
1201 if (strcmp(VerTag,Ver.VerStr()) != 0)
1202 {
1203 ioprintf(c1out,_("Selected version %s (%s) for %s\n"),
1204 Ver.VerStr(),Ver.RelStr().c_str(),Pkg.Name());
1205 }
1206
1207 Cache.SetCandidateVersion(Ver);
1208 return true;
1209 }
1210 /*}}}*/
1211 // FindSrc - Find a source record /*{{{*/
1212 // ---------------------------------------------------------------------
1213 /* */
1214 pkgSrcRecords::Parser *FindSrc(const char *Name,pkgRecords &Recs,
1215 pkgSrcRecords &SrcRecs,string &Src,
1216 pkgDepCache &Cache)
1217 {
1218 // We want to pull the version off the package specification..
1219 string VerTag;
1220 string TmpSrc = Name;
1221 string::size_type Slash = TmpSrc.rfind('=');
1222
1223 // honor default release
1224 string DefRel = _config->Find("APT::Default-Release");
1225 pkgCache::PkgIterator Pkg = Cache.FindPkg(TmpSrc);
1226
1227 if (Slash != string::npos)
1228 {
1229 VerTag = string(TmpSrc.begin() + Slash + 1,TmpSrc.end());
1230 TmpSrc = string(TmpSrc.begin(),TmpSrc.begin() + Slash);
1231 }
1232 else if(!Pkg.end() && DefRel.empty() == false)
1233 {
1234 // we have a default release, try to locate the pkg. we do it like
1235 // this because GetCandidateVer() will not "downgrade", that means
1236 // "apt-get source -t stable apt" won't work on a unstable system
1237 for (pkgCache::VerIterator Ver = Pkg.VersionList(); Ver.end() == false;
1238 Ver++)
1239 {
1240 for (pkgCache::VerFileIterator VF = Ver.FileList(); VF.end() == false;
1241 VF++)
1242 {
1243 /* If this is the status file, and the current version is not the
1244 version in the status file (ie it is not installed, or somesuch)
1245 then it is not a candidate for installation, ever. This weeds
1246 out bogus entries that may be due to config-file states, or
1247 other. */
1248 if ((VF.File()->Flags & pkgCache::Flag::NotSource) ==
1249 pkgCache::Flag::NotSource && Pkg.CurrentVer() != Ver)
1250 continue;
1251
1252 //std::cout << VF.File().Archive() << std::endl;
1253 if(VF.File().Archive() && (VF.File().Archive() == DefRel))
1254 {
1255 VerTag = Ver.VerStr();
1256 break;
1257 }
1258 }
1259 }
1260 }
1261
1262 /* Lookup the version of the package we would install if we were to
1263 install a version and determine the source package name, then look
1264 in the archive for a source package of the same name. */
1265 if (_config->FindB("APT::Get::Only-Source") == false)
1266 {
1267 if (Pkg.end() == false)
1268 {
1269 pkgCache::VerIterator Ver = Cache.GetCandidateVer(Pkg);
1270 if (Ver.end() == false)
1271 {
1272 pkgRecords::Parser &Parse = Recs.Lookup(Ver.FileList());
1273 Src = Parse.SourcePkg();
1274 }
1275 }
1276 }
1277
1278 // No source package name..
1279 if (Src.empty() == true)
1280 Src = TmpSrc;
1281
1282 // The best hit
1283 pkgSrcRecords::Parser *Last = 0;
1284 unsigned long Offset = 0;
1285 string Version;
1286 bool IsMatch = false;
1287
1288 // If we are matching by version then we need exact matches to be happy
1289 if (VerTag.empty() == false)
1290 IsMatch = true;
1291
1292 /* Iterate over all of the hits, which includes the resulting
1293 binary packages in the search */
1294 pkgSrcRecords::Parser *Parse;
1295 SrcRecs.Restart();
1296 while ((Parse = SrcRecs.Find(Src.c_str(),false)) != 0)
1297 {
1298 string Ver = Parse->Version();
1299
1300 // Skip name mismatches
1301 if (IsMatch == true && Parse->Package() != Src)
1302 continue;
1303
1304 if (VerTag.empty() == false)
1305 {
1306 /* Don't want to fall through because we are doing exact version
1307 matching. */
1308 if (Cache.VS().CmpVersion(VerTag,Ver) != 0)
1309 continue;
1310
1311 Last = Parse;
1312 Offset = Parse->Offset();
1313 break;
1314 }
1315
1316 // Newer version or an exact match
1317 if (Last == 0 || Cache.VS().CmpVersion(Version,Ver) < 0 ||
1318 (Parse->Package() == Src && IsMatch == false))
1319 {
1320 IsMatch = Parse->Package() == Src;
1321 Last = Parse;
1322 Offset = Parse->Offset();
1323 Version = Ver;
1324 }
1325 }
1326
1327 if (Last == 0 || Last->Jump(Offset) == false)
1328 return 0;
1329
1330 return Last;
1331 }
1332 /*}}}*/
1333
1334 // DoUpdate - Update the package lists /*{{{*/
1335 // ---------------------------------------------------------------------
1336 /* */
1337 bool DoUpdate(CommandLine &CmdL)
1338 {
1339 if (CmdL.FileSize() != 1)
1340 return _error->Error(_("The update command takes no arguments"));
1341
1342 // Get the source list
1343 pkgSourceList List;
1344 if (List.ReadMainList() == false)
1345 return false;
1346
1347 // Lock the list directory
1348 FileFd Lock;
1349 if (_config->FindB("Debug::NoLocking",false) == false)
1350 {
1351 Lock.Fd(GetLock(_config->FindDir("Dir::State::Lists") + "lock"));
1352 if (_error->PendingError() == true)
1353 return _error->Error(_("Unable to lock the list directory"));
1354 }
1355
1356 // Create the progress
1357 AcqTextStatus Stat(ScreenWidth,_config->FindI("quiet",0));
1358
1359 // Just print out the uris an exit if the --print-uris flag was used
1360 if (_config->FindB("APT::Get::Print-URIs") == true)
1361 {
1362 // get a fetcher
1363 pkgAcquire Fetcher(&Stat);
1364
1365 // Populate it with the source selection and get all Indexes
1366 // (GetAll=true)
1367 if (List.GetIndexes(&Fetcher,true) == false)
1368 return false;
1369
1370 pkgAcquire::UriIterator I = Fetcher.UriBegin();
1371 for (; I != Fetcher.UriEnd(); I++)
1372 cout << '\'' << I->URI << "' " << flNotDir(I->Owner->DestFile) << ' ' <<
1373 I->Owner->FileSize << ' ' << I->Owner->HashSum() << endl;
1374 return true;
1375 }
1376
1377 // do the work
1378 CacheFile Cache;
1379 if (_config->FindB("APT::Get::Download",true) == true)
1380 ListUpdate(Stat, List);
1381
1382 // Rebuild the cache.
1383 if (Cache.BuildCaches() == false)
1384 return false;
1385
1386 return true;
1387 }
1388 /*}}}*/
1389 // DoAutomaticRemove - Remove all automatic unused packages /*{{{*/
1390 // ---------------------------------------------------------------------
1391 /* Remove unused automatic packages */
1392 bool DoAutomaticRemove(CacheFile &Cache)
1393 {
1394 bool Debug = _config->FindI("Debug::pkgAutoRemove",false);
1395 bool doAutoRemove = _config->FindB("APT::Get::AutomaticRemove", false);
1396 bool hideAutoRemove = _config->FindB("APT::Get::HideAutoRemove");
1397 pkgDepCache::ActionGroup group(*Cache);
1398
1399 if(Debug)
1400 std::cout << "DoAutomaticRemove()" << std::endl;
1401
1402 if (_config->FindB("APT::Get::Remove",true) == false &&
1403 doAutoRemove == true)
1404 {
1405 c1out << _("We are not supposed to delete stuff, can't start "
1406 "AutoRemover") << std::endl;
1407 doAutoRemove = false;
1408 }
1409
1410 string autoremovelist, autoremoveversions;
1411 // look over the cache to see what can be removed
1412 for (pkgCache::PkgIterator Pkg = Cache->PkgBegin(); ! Pkg.end(); ++Pkg)
1413 {
1414 if (Cache[Pkg].Garbage)
1415 {
1416 if(Pkg.CurrentVer() != 0 || Cache[Pkg].Install())
1417 if(Debug)
1418 std::cout << "We could delete %s" << Pkg.Name() << std::endl;
1419
1420 // only show stuff in the list that is not yet marked for removal
1421 if(Cache[Pkg].Delete() == false)
1422 {
1423 autoremovelist += string(Pkg.Name()) + " ";
1424 autoremoveversions += string(Cache[Pkg].CandVersion) + "\n";
1425 }
1426 if (doAutoRemove)
1427 {
1428 if(Pkg.CurrentVer() != 0 &&
1429 Pkg->CurrentState != pkgCache::State::ConfigFiles)
1430 Cache->MarkDelete(Pkg, _config->FindB("APT::Get::Purge", false));
1431 else
1432 Cache->MarkKeep(Pkg, false, false);
1433 }
1434 }
1435 }
1436 if (!hideAutoRemove)
1437 ShowList(c1out, _("The following packages were automatically installed and are no longer required:"), autoremovelist, autoremoveversions);
1438 if (!doAutoRemove && !hideAutoRemove && autoremovelist.size() > 0)
1439 c1out << _("Use 'apt-get autoremove' to remove them.") << std::endl;
1440
1441 // Now see if we destroyed anything
1442 if (Cache->BrokenCount() != 0)
1443 {
1444 c1out << _("Hmm, seems like the AutoRemover destroyed something which really\n"
1445 "shouldn't happen. Please file a bug report against apt.") << endl;
1446 c1out << endl;
1447 c1out << _("The following information may help to resolve the situation:") << endl;
1448 c1out << endl;
1449 ShowBroken(c1out,Cache,false);
1450
1451 return _error->Error(_("Internal Error, AutoRemover broke stuff"));
1452 }
1453 return true;
1454 }
1455
1456 // DoUpgrade - Upgrade all packages /*{{{*/
1457 // ---------------------------------------------------------------------
1458 /* Upgrade all packages without installing new packages or erasing old
1459 packages */
1460 bool DoUpgrade(CommandLine &CmdL)
1461 {
1462 CacheFile Cache;
1463 if (Cache.OpenForInstall() == false || Cache.CheckDeps() == false)
1464 return false;
1465
1466 // Do the upgrade
1467 if (pkgAllUpgrade(Cache) == false)
1468 {
1469 ShowBroken(c1out,Cache,false);
1470 return _error->Error(_("Internal error, AllUpgrade broke stuff"));
1471 }
1472
1473 return InstallPackages(Cache,true);
1474 }
1475 /*}}}*/
1476 // DoInstallTask - Install task from the command line /*{{{*/
1477 // ---------------------------------------------------------------------
1478 /* Install named task */
1479 bool TryInstallTask(pkgDepCache &Cache, pkgProblemResolver &Fix,
1480 bool BrokenFix,
1481 unsigned int& ExpectedInst,
1482 const char *taskname,
1483 bool Remove)
1484 {
1485 const char *start, *end;
1486 pkgCache::PkgIterator Pkg;
1487 char buf[64*1024];
1488 regex_t Pattern;
1489
1490 // get the records
1491 pkgRecords Recs(Cache);
1492
1493 // build regexp for the task
1494 char S[300];
1495 snprintf(S, sizeof(S), "^Task:.*[, ]%s([, ]|$)", taskname);
1496 if(regcomp(&Pattern,S, REG_EXTENDED | REG_NOSUB | REG_NEWLINE) != 0)
1497 return _error->Error("Failed to compile task regexp");
1498
1499 bool found = false;
1500 bool res = true;
1501
1502 // two runs, first ignore dependencies, second install any missing
1503 for(int IgnoreBroken=1; IgnoreBroken >= 0; IgnoreBroken--)
1504 {
1505 for (Pkg = Cache.PkgBegin(); Pkg.end() == false; Pkg++)
1506 {
1507 pkgCache::VerIterator ver = Cache[Pkg].CandidateVerIter(Cache);
1508 if(ver.end())
1509 continue;
1510 pkgRecords::Parser &parser = Recs.Lookup(ver.FileList());
1511 parser.GetRec(start,end);
1512 strncpy(buf, start, end-start);
1513 buf[end-start] = 0x0;
1514 if (regexec(&Pattern,buf,0,0,0) != 0)
1515 continue;
1516 res &= TryToInstall(Pkg,Cache,Fix,Remove,IgnoreBroken,ExpectedInst);
1517 found = true;
1518 }
1519 }
1520
1521 // now let the problem resolver deal with any issues
1522 Fix.Resolve(true);
1523
1524 if(!found)
1525 _error->Error(_("Couldn't find task %s"),taskname);
1526
1527 regfree(&Pattern);
1528 return res;
1529 }
1530
1531 // DoInstall - Install packages from the command line /*{{{*/
1532 // ---------------------------------------------------------------------
1533 /* Install named packages */
1534 bool DoInstall(CommandLine &CmdL)
1535 {
1536 CacheFile Cache;
1537 if (Cache.OpenForInstall() == false ||
1538 Cache.CheckDeps(CmdL.FileSize() != 1) == false)
1539 return false;
1540
1541 // Enter the special broken fixing mode if the user specified arguments
1542 bool BrokenFix = false;
1543 if (Cache->BrokenCount() != 0)
1544 BrokenFix = true;
1545
1546 unsigned int AutoMarkChanged = 0;
1547 unsigned int ExpectedInst = 0;
1548 unsigned int Packages = 0;
1549 pkgProblemResolver Fix(Cache);
1550
1551 bool DefRemove = false;
1552 if (strcasecmp(CmdL.FileList[0],"remove") == 0)
1553 DefRemove = true;
1554 else if (strcasecmp(CmdL.FileList[0], "purge") == 0)
1555 {
1556 _config->Set("APT::Get::Purge", true);
1557 DefRemove = true;
1558 }
1559 else if (strcasecmp(CmdL.FileList[0], "autoremove") == 0)
1560 {
1561 _config->Set("APT::Get::AutomaticRemove", "true");
1562 DefRemove = true;
1563 }
1564 // new scope for the ActionGroup
1565 {
1566 pkgDepCache::ActionGroup group(Cache);
1567 for (const char **I = CmdL.FileList + 1; *I != 0; I++)
1568 {
1569 // Duplicate the string
1570 unsigned int Length = strlen(*I);
1571 char S[300];
1572 if (Length >= sizeof(S))
1573 continue;
1574 strcpy(S,*I);
1575
1576 // See if we are removing and special indicators..
1577 bool Remove = DefRemove;
1578 char *VerTag = 0;
1579 bool VerIsRel = false;
1580
1581 // this is a task!
1582 if (Length >= 1 && S[Length - 1] == '^')
1583 {
1584 S[--Length] = 0;
1585 // tasks must always be confirmed
1586 ExpectedInst += 1000;
1587 // see if we can install it
1588 TryInstallTask(Cache, Fix, BrokenFix, ExpectedInst, S, Remove);
1589 continue;
1590 }
1591
1592 while (Cache->FindPkg(S).end() == true)
1593 {
1594 // Handle an optional end tag indicating what to do
1595 if (Length >= 1 && S[Length - 1] == '-')
1596 {
1597 Remove = true;
1598 S[--Length] = 0;
1599 continue;
1600 }
1601
1602 if (Length >= 1 && S[Length - 1] == '+')
1603 {
1604 Remove = false;
1605 S[--Length] = 0;
1606 continue;
1607 }
1608
1609 char *Slash = strchr(S,'=');
1610 if (Slash != 0)
1611 {
1612 VerIsRel = false;
1613 *Slash = 0;
1614 VerTag = Slash + 1;
1615 }
1616
1617 Slash = strchr(S,'/');
1618 if (Slash != 0)
1619 {
1620 VerIsRel = true;
1621 *Slash = 0;
1622 VerTag = Slash + 1;
1623 }
1624
1625 break;
1626 }
1627
1628 // Locate the package
1629 pkgCache::PkgIterator Pkg = Cache->FindPkg(S);
1630 Packages++;
1631 if (Pkg.end() == true)
1632 {
1633 // Check if the name is a regex
1634 const char *I;
1635 for (I = S; *I != 0; I++)
1636 if (*I == '?' || *I == '*' || *I == '|' ||
1637 *I == '[' || *I == '^' || *I == '$')
1638 break;
1639 if (*I == 0)
1640 return _error->Error(_("Couldn't find package %s"),S);
1641
1642 // Regexs must always be confirmed
1643 ExpectedInst += 1000;
1644
1645 // Compile the regex pattern
1646 regex_t Pattern;
1647 int Res;
1648 if ((Res = regcomp(&Pattern,S,REG_EXTENDED | REG_ICASE |
1649 REG_NOSUB)) != 0)
1650 {
1651 char Error[300];
1652 regerror(Res,&Pattern,Error,sizeof(Error));
1653 return _error->Error(_("Regex compilation error - %s"),Error);
1654 }
1655
1656 // Run over the matches
1657 bool Hit = false;
1658 for (Pkg = Cache->PkgBegin(); Pkg.end() == false; Pkg++)
1659 {
1660 if (regexec(&Pattern,Pkg.Name(),0,0,0) != 0)
1661 continue;
1662
1663 ioprintf(c1out,_("Note, selecting %s for regex '%s'\n"),
1664 Pkg.Name(),S);
1665
1666 if (VerTag != 0)
1667 if (TryToChangeVer(Pkg,Cache,VerTag,VerIsRel) == false)
1668 return false;
1669
1670 Hit |= TryToInstall(Pkg,Cache,Fix,Remove,BrokenFix,
1671 ExpectedInst,false);
1672 }
1673 regfree(&Pattern);
1674
1675 if (Hit == false)
1676 return _error->Error(_("Couldn't find package %s"),S);
1677 }
1678 else
1679 {
1680 if (VerTag != 0)
1681 if (TryToChangeVer(Pkg,Cache,VerTag,VerIsRel) == false)
1682 return false;
1683 if (TryToInstall(Pkg,Cache,Fix,Remove,BrokenFix,ExpectedInst) == false)
1684 return false;
1685
1686 // see if we need to fix the auto-mark flag
1687 // e.g. apt-get install foo
1688 // where foo is marked automatic
1689 if(!Remove &&
1690 Cache[Pkg].Install() == false &&
1691 (Cache[Pkg].Flags & pkgCache::Flag::Auto) &&
1692 _config->FindB("APT::Get::ReInstall",false) == false)
1693 {
1694 ioprintf(c1out,_("%s set to manually installed.\n"),
1695 Pkg.Name());
1696 Cache->MarkAuto(Pkg,false);
1697 AutoMarkChanged++;
1698 }
1699 }
1700 }
1701
1702 /* If we are in the Broken fixing mode we do not attempt to fix the
1703 problems. This is if the user invoked install without -f and gave
1704 packages */
1705 if (BrokenFix == true && Cache->BrokenCount() != 0)
1706 {
1707 c1out << _("You might want to run `apt-get -f install' to correct these:") << endl;
1708 ShowBroken(c1out,Cache,false);
1709
1710 return _error->Error(_("Unmet dependencies. Try 'apt-get -f install' with no packages (or specify a solution)."));
1711 }
1712
1713 // Call the scored problem resolver
1714 Fix.InstallProtect();
1715 if (Fix.Resolve(true) == false)
1716 _error->Discard();
1717
1718 // Now we check the state of the packages,
1719 if (Cache->BrokenCount() != 0)
1720 {
1721 c1out <<
1722 _("Some packages could not be installed. This may mean that you have\n"
1723 "requested an impossible situation or if you are using the unstable\n"
1724 "distribution that some required packages have not yet been created\n"
1725 "or been moved out of Incoming.") << endl;
1726 /*
1727 if (Packages == 1)
1728 {
1729 c1out << endl;
1730 c1out <<
1731 _("Since you only requested a single operation it is extremely likely that\n"
1732 "the package is simply not installable and a bug report against\n"
1733 "that package should be filed.") << endl;
1734 }
1735 */
1736
1737 c1out << _("The following information may help to resolve the situation:") << endl;
1738 c1out << endl;
1739 ShowBroken(c1out,Cache,false);
1740 return _error->Error(_("Broken packages"));
1741 }
1742 }
1743 if (!DoAutomaticRemove(Cache))
1744 return false;
1745
1746 /* Print out a list of packages that are going to be installed extra
1747 to what the user asked */
1748 if (Cache->InstCount() != ExpectedInst)
1749 {
1750 string List;
1751 string VersionsList;
1752 for (unsigned J = 0; J < Cache->Head().PackageCount; J++)
1753 {
1754 pkgCache::PkgIterator I(Cache,Cache.List[J]);
1755 if ((*Cache)[I].Install() == false)
1756 continue;
1757
1758 const char **J;
1759 for (J = CmdL.FileList + 1; *J != 0; J++)
1760 if (strcmp(*J,I.Name()) == 0)
1761 break;
1762
1763 if (*J == 0) {
1764 List += string(I.Name()) + " ";
1765 VersionsList += string(Cache[I].CandVersion) + "\n";
1766 }
1767 }
1768
1769 ShowList(c1out,_("The following extra packages will be installed:"),List,VersionsList);
1770 }
1771
1772 /* Print out a list of suggested and recommended packages */
1773 {
1774 string SuggestsList, RecommendsList, List;
1775 string SuggestsVersions, RecommendsVersions;
1776 for (unsigned J = 0; J < Cache->Head().PackageCount; J++)
1777 {
1778 pkgCache::PkgIterator Pkg(Cache,Cache.List[J]);
1779
1780 /* Just look at the ones we want to install */
1781 if ((*Cache)[Pkg].Install() == false)
1782 continue;
1783
1784 // get the recommends/suggests for the candidate ver
1785 pkgCache::VerIterator CV = (*Cache)[Pkg].CandidateVerIter(*Cache);
1786 for (pkgCache::DepIterator D = CV.DependsList(); D.end() == false; )
1787 {
1788 pkgCache::DepIterator Start;
1789 pkgCache::DepIterator End;
1790 D.GlobOr(Start,End); // advances D
1791
1792 // FIXME: we really should display a or-group as a or-group to the user
1793 // the problem is that ShowList is incapable of doing this
1794 string RecommendsOrList,RecommendsOrVersions;
1795 string SuggestsOrList,SuggestsOrVersions;
1796 bool foundInstalledInOrGroup = false;
1797 for(;;)
1798 {
1799 /* Skip if package is installed already, or is about to be */
1800 string target = string(Start.TargetPkg().Name()) + " ";
1801
1802 if ((*Start.TargetPkg()).SelectedState == pkgCache::State::Install
1803 || Cache[Start.TargetPkg()].Install())
1804 {
1805 foundInstalledInOrGroup=true;
1806 break;
1807 }
1808
1809 /* Skip if we already saw it */
1810 if (int(SuggestsList.find(target)) != -1 || int(RecommendsList.find(target)) != -1)
1811 {
1812 foundInstalledInOrGroup=true;
1813 break;
1814 }
1815
1816 // this is a dep on a virtual pkg, check if any package that provides it
1817 // should be installed
1818 if(Start.TargetPkg().ProvidesList() != 0)
1819 {
1820 pkgCache::PrvIterator I = Start.TargetPkg().ProvidesList();
1821 for (; I.end() == false; I++)
1822 {
1823 pkgCache::PkgIterator Pkg = I.OwnerPkg();
1824 if (Cache[Pkg].CandidateVerIter(Cache) == I.OwnerVer() &&
1825 Pkg.CurrentVer() != 0)
1826 foundInstalledInOrGroup=true;
1827 }
1828 }
1829
1830 if (Start->Type == pkgCache::Dep::Suggests)
1831 {
1832 SuggestsOrList += target;
1833 SuggestsOrVersions += string(Cache[Start.TargetPkg()].CandVersion) + "\n";
1834 }
1835
1836 if (Start->Type == pkgCache::Dep::Recommends)
1837 {
1838 RecommendsOrList += target;
1839 RecommendsOrVersions += string(Cache[Start.TargetPkg()].CandVersion) + "\n";
1840 }
1841
1842 if (Start >= End)
1843 break;
1844 Start++;
1845 }
1846
1847 if(foundInstalledInOrGroup == false)
1848 {
1849 RecommendsList += RecommendsOrList;
1850 RecommendsVersions += RecommendsOrVersions;
1851 SuggestsList += SuggestsOrList;
1852 SuggestsVersions += SuggestsOrVersions;
1853 }
1854
1855 }
1856 }
1857
1858 ShowList(c1out,_("Suggested packages:"),SuggestsList,SuggestsVersions);
1859 ShowList(c1out,_("Recommended packages:"),RecommendsList,RecommendsVersions);
1860
1861 }
1862
1863 // if nothing changed in the cache, but only the automark information
1864 // we write the StateFile here, otherwise it will be written in
1865 // cache.commit()
1866 if (AutoMarkChanged > 0 &&
1867 Cache->DelCount() == 0 && Cache->InstCount() == 0 &&
1868 Cache->BadCount() == 0)
1869 Cache->writeStateFile(NULL);
1870
1871 // See if we need to prompt
1872 if (Cache->InstCount() == ExpectedInst && Cache->DelCount() == 0)
1873 return InstallPackages(Cache,false,false);
1874
1875 return InstallPackages(Cache,false);
1876 }
1877 /*}}}*/
1878 // DoDistUpgrade - Automatic smart upgrader /*{{{*/
1879 // ---------------------------------------------------------------------
1880 /* Intelligent upgrader that will install and remove packages at will */
1881 bool DoDistUpgrade(CommandLine &CmdL)
1882 {
1883 CacheFile Cache;
1884 if (Cache.OpenForInstall() == false || Cache.CheckDeps() == false)
1885 return false;
1886
1887 c0out << _("Calculating upgrade... ") << flush;
1888 if (pkgDistUpgrade(*Cache) == false)
1889 {
1890 c0out << _("Failed") << endl;
1891 ShowBroken(c1out,Cache,false);
1892 return false;
1893 }
1894
1895 c0out << _("Done") << endl;
1896
1897 return InstallPackages(Cache,true);
1898 }
1899 /*}}}*/
1900 // DoDSelectUpgrade - Do an upgrade by following dselects selections /*{{{*/
1901 // ---------------------------------------------------------------------
1902 /* Follows dselect's selections */
1903 bool DoDSelectUpgrade(CommandLine &CmdL)
1904 {
1905 CacheFile Cache;
1906 if (Cache.OpenForInstall() == false || Cache.CheckDeps() == false)
1907 return false;
1908
1909 pkgDepCache::ActionGroup group(Cache);
1910
1911 // Install everything with the install flag set
1912 pkgCache::PkgIterator I = Cache->PkgBegin();
1913 for (;I.end() != true; I++)
1914 {
1915 /* Install the package only if it is a new install, the autoupgrader
1916 will deal with the rest */
1917 if (I->SelectedState == pkgCache::State::Install)
1918 Cache->MarkInstall(I,false);
1919 }
1920
1921 /* Now install their deps too, if we do this above then order of
1922 the status file is significant for | groups */
1923 for (I = Cache->PkgBegin();I.end() != true; I++)
1924 {
1925 /* Install the package only if it is a new install, the autoupgrader
1926 will deal with the rest */
1927 if (I->SelectedState == pkgCache::State::Install)
1928 Cache->MarkInstall(I,true);
1929 }
1930
1931 // Apply erasures now, they override everything else.
1932 for (I = Cache->PkgBegin();I.end() != true; I++)
1933 {
1934 // Remove packages
1935 if (I->SelectedState == pkgCache::State::DeInstall ||
1936 I->SelectedState == pkgCache::State::Purge)
1937 Cache->MarkDelete(I,I->SelectedState == pkgCache::State::Purge);
1938 }
1939
1940 /* Resolve any problems that dselect created, allupgrade cannot handle
1941 such things. We do so quite agressively too.. */
1942 if (Cache->BrokenCount() != 0)
1943 {
1944 pkgProblemResolver Fix(Cache);
1945
1946 // Hold back held packages.
1947 if (_config->FindB("APT::Ignore-Hold",false) == false)
1948 {
1949 for (pkgCache::PkgIterator I = Cache->PkgBegin(); I.end() == false; I++)
1950 {
1951 if (I->SelectedState == pkgCache::State::Hold)
1952 {
1953 Fix.Protect(I);
1954 Cache->MarkKeep(I);
1955 }
1956 }
1957 }
1958
1959 if (Fix.Resolve() == false)
1960 {
1961 ShowBroken(c1out,Cache,false);
1962 return _error->Error(_("Internal error, problem resolver broke stuff"));
1963 }
1964 }
1965
1966 // Now upgrade everything
1967 if (pkgAllUpgrade(Cache) == false)
1968 {
1969 ShowBroken(c1out,Cache,false);
1970 return _error->Error(_("Internal error, problem resolver broke stuff"));
1971 }
1972
1973 return InstallPackages(Cache,false);
1974 }
1975 /*}}}*/
1976 // DoClean - Remove download archives /*{{{*/
1977 // ---------------------------------------------------------------------
1978 /* */
1979 bool DoClean(CommandLine &CmdL)
1980 {
1981 if (_config->FindB("APT::Get::Simulate") == true)
1982 {
1983 cout << "Del " << _config->FindDir("Dir::Cache::archives") << "* " <<
1984 _config->FindDir("Dir::Cache::archives") << "partial/*" << endl;
1985 return true;
1986 }
1987
1988 // Lock the archive directory
1989 FileFd Lock;
1990 if (_config->FindB("Debug::NoLocking",false) == false)
1991 {
1992 Lock.Fd(GetLock(_config->FindDir("Dir::Cache::Archives") + "lock"));
1993 if (_error->PendingError() == true)
1994 return _error->Error(_("Unable to lock the download directory"));
1995 }
1996
1997 pkgAcquire Fetcher;
1998 Fetcher.Clean(_config->FindDir("Dir::Cache::archives"));
1999 Fetcher.Clean(_config->FindDir("Dir::Cache::archives") + "partial/");
2000 return true;
2001 }
2002 /*}}}*/
2003 // DoAutoClean - Smartly remove downloaded archives /*{{{*/
2004 // ---------------------------------------------------------------------
2005 /* This is similar to clean but it only purges things that cannot be
2006 downloaded, that is old versions of cached packages. */
2007 class LogCleaner : public pkgArchiveCleaner
2008 {
2009 protected:
2010 virtual void Erase(const char *File,string Pkg,string Ver,struct stat &St)
2011 {
2012 c1out << "Del " << Pkg << " " << Ver << " [" << SizeToStr(St.st_size) << "B]" << endl;
2013
2014 if (_config->FindB("APT::Get::Simulate") == false)
2015 unlink(File);
2016 };
2017 };
2018
2019 bool DoAutoClean(CommandLine &CmdL)
2020 {
2021 // Lock the archive directory
2022 FileFd Lock;
2023 if (_config->FindB("Debug::NoLocking",false) == false)
2024 {
2025 Lock.Fd(GetLock(_config->FindDir("Dir::Cache::Archives") + "lock"));
2026 if (_error->PendingError() == true)
2027 return _error->Error(_("Unable to lock the download directory"));
2028 }
2029
2030 CacheFile Cache;
2031 if (Cache.Open() == false)
2032 return false;
2033
2034 LogCleaner Cleaner;
2035
2036 return Cleaner.Go(_config->FindDir("Dir::Cache::archives"),*Cache) &&
2037 Cleaner.Go(_config->FindDir("Dir::Cache::archives") + "partial/",*Cache);
2038 }
2039 /*}}}*/
2040 // DoCheck - Perform the check operation /*{{{*/
2041 // ---------------------------------------------------------------------
2042 /* Opening automatically checks the system, this command is mostly used
2043 for debugging */
2044 bool DoCheck(CommandLine &CmdL)
2045 {
2046 CacheFile Cache;
2047 Cache.Open();
2048 Cache.CheckDeps();
2049
2050 return true;
2051 }
2052 /*}}}*/
2053 // DoSource - Fetch a source archive /*{{{*/
2054 // ---------------------------------------------------------------------
2055 /* Fetch souce packages */
2056 struct DscFile
2057 {
2058 string Package;
2059 string Version;
2060 string Dsc;
2061 };
2062
2063 bool DoSource(CommandLine &CmdL)
2064 {
2065 CacheFile Cache;
2066 if (Cache.Open(false) == false)
2067 return false;
2068
2069 if (CmdL.FileSize() <= 1)
2070 return _error->Error(_("Must specify at least one package to fetch source for"));
2071
2072 // Read the source list
2073 pkgSourceList List;
2074 if (List.ReadMainList() == false)
2075 return _error->Error(_("The list of sources could not be read."));
2076
2077 // Create the text record parsers
2078 pkgRecords Recs(Cache);
2079 pkgSrcRecords SrcRecs(List);
2080 if (_error->PendingError() == true)
2081 return false;
2082
2083 // Create the download object
2084 AcqTextStatus Stat(ScreenWidth,_config->FindI("quiet",0));
2085 pkgAcquire Fetcher(&Stat);
2086
2087 DscFile *Dsc = new DscFile[CmdL.FileSize()];
2088
2089 // insert all downloaded uris into this set to avoid downloading them
2090 // twice
2091 set<string> queued;
2092 // Load the requestd sources into the fetcher
2093 unsigned J = 0;
2094 for (const char **I = CmdL.FileList + 1; *I != 0; I++, J++)
2095 {
2096 string Src;
2097 pkgSrcRecords::Parser *Last = FindSrc(*I,Recs,SrcRecs,Src,*Cache);
2098
2099 if (Last == 0)
2100 return _error->Error(_("Unable to find a source package for %s"),Src.c_str());
2101
2102 // Back track
2103 vector<pkgSrcRecords::File> Lst;
2104 if (Last->Files(Lst) == false)
2105 return false;
2106
2107 // Load them into the fetcher
2108 for (vector<pkgSrcRecords::File>::const_iterator I = Lst.begin();
2109 I != Lst.end(); I++)
2110 {
2111 // Try to guess what sort of file it is we are getting.
2112 if (I->Type == "dsc")
2113 {
2114 Dsc[J].Package = Last->Package();
2115 Dsc[J].Version = Last->Version();
2116 Dsc[J].Dsc = flNotDir(I->Path);
2117 }
2118
2119 // Diff only mode only fetches .diff files
2120 if (_config->FindB("APT::Get::Diff-Only",false) == true &&
2121 I->Type != "diff")
2122 continue;
2123
2124 // Tar only mode only fetches .tar files
2125 if (_config->FindB("APT::Get::Tar-Only",false) == true &&
2126 I->Type != "tar")
2127 continue;
2128
2129 // Dsc only mode only fetches .dsc files
2130 if (_config->FindB("APT::Get::Dsc-Only",false) == true &&
2131 I->Type != "dsc")
2132 continue;
2133
2134 // don't download the same uri twice (should this be moved to
2135 // the fetcher interface itself?)
2136 if(queued.find(Last->Index().ArchiveURI(I->Path)) != queued.end())
2137 continue;
2138 queued.insert(Last->Index().ArchiveURI(I->Path));
2139
2140 // check if we have a file with that md5 sum already localy
2141 if(!I->MD5Hash.empty() && FileExists(flNotDir(I->Path)))
2142 {
2143 FileFd Fd(flNotDir(I->Path), FileFd::ReadOnly);
2144 MD5Summation sum;
2145 sum.AddFD(Fd.Fd(), Fd.Size());
2146 Fd.Close();
2147 if((string)sum.Result() == I->MD5Hash)
2148 {
2149 ioprintf(c1out,_("Skipping already downloaded file '%s'\n"),
2150 flNotDir(I->Path).c_str());
2151 continue;
2152 }
2153 }
2154
2155 new pkgAcqFile(&Fetcher,Last->Index().ArchiveURI(I->Path),
2156 I->MD5Hash,I->Size,
2157 Last->Index().SourceInfo(*Last,*I),Src);
2158 }
2159 }
2160
2161 // Display statistics
2162 double FetchBytes = Fetcher.FetchNeeded();
2163 double FetchPBytes = Fetcher.PartialPresent();
2164 double DebBytes = Fetcher.TotalNeeded();
2165
2166 // Check for enough free space
2167 struct statvfs Buf;
2168 string OutputDir = ".";
2169 if (statvfs(OutputDir.c_str(),&Buf) != 0)
2170 return _error->Errno("statvfs",_("Couldn't determine free space in %s"),
2171 OutputDir.c_str());
2172 if (unsigned(Buf.f_bfree) < (FetchBytes - FetchPBytes)/Buf.f_bsize)
2173 {
2174 struct statfs Stat;
2175 if (statfs(OutputDir.c_str(),&Stat) != 0 ||
2176 unsigned(Stat.f_type) != RAMFS_MAGIC)
2177 return _error->Error(_("You don't have enough free space in %s"),
2178 OutputDir.c_str());
2179 }
2180
2181 // Number of bytes
2182 if (DebBytes != FetchBytes)
2183 ioprintf(c1out,_("Need to get %sB/%sB of source archives.\n"),
2184 SizeToStr(FetchBytes).c_str(),SizeToStr(DebBytes).c_str());
2185 else
2186 ioprintf(c1out,_("Need to get %sB of source archives.\n"),
2187 SizeToStr(DebBytes).c_str());
2188
2189 if (_config->FindB("APT::Get::Simulate",false) == true)
2190 {
2191 for (unsigned I = 0; I != J; I++)
2192 ioprintf(cout,_("Fetch source %s\n"),Dsc[I].Package.c_str());
2193 return true;
2194 }
2195
2196 // Just print out the uris an exit if the --print-uris flag was used
2197 if (_config->FindB("APT::Get::Print-URIs") == true)
2198 {
2199 pkgAcquire::UriIterator I = Fetcher.UriBegin();
2200 for (; I != Fetcher.UriEnd(); I++)
2201 cout << '\'' << I->URI << "' " << flNotDir(I->Owner->DestFile) << ' ' <<
2202 I->Owner->FileSize << ' ' << I->Owner->HashSum() << endl;
2203 return true;
2204 }
2205
2206 // Run it
2207 if (Fetcher.Run() == pkgAcquire::Failed)
2208 return false;
2209
2210 // Print error messages
2211 bool Failed = false;
2212 for (pkgAcquire::ItemIterator I = Fetcher.ItemsBegin(); I != Fetcher.ItemsEnd(); I++)
2213 {
2214 if ((*I)->Status == pkgAcquire::Item::StatDone &&
2215 (*I)->Complete == true)
2216 continue;
2217
2218 fprintf(stderr,_("Failed to fetch %s %s\n"),(*I)->DescURI().c_str(),
2219 (*I)->ErrorText.c_str());
2220 Failed = true;
2221 }
2222 if (Failed == true)
2223 return _error->Error(_("Failed to fetch some archives."));
2224
2225 if (_config->FindB("APT::Get::Download-only",false) == true)
2226 {
2227 c1out << _("Download complete and in download only mode") << endl;
2228 return true;
2229 }
2230
2231 // Unpack the sources
2232 pid_t Process = ExecFork();
2233
2234 if (Process == 0)
2235 {
2236 for (unsigned I = 0; I != J; I++)
2237 {
2238 string Dir = Dsc[I].Package + '-' + Cache->VS().UpstreamVersion(Dsc[I].Version.c_str());
2239
2240 // Diff only mode only fetches .diff files
2241 if (_config->FindB("APT::Get::Diff-Only",false) == true ||
2242 _config->FindB("APT::Get::Tar-Only",false) == true ||
2243 Dsc[I].Dsc.empty() == true)
2244 continue;
2245
2246 // See if the package is already unpacked
2247 struct stat Stat;
2248 if (stat(Dir.c_str(),&Stat) == 0 &&
2249 S_ISDIR(Stat.st_mode) != 0)
2250 {
2251 ioprintf(c0out ,_("Skipping unpack of already unpacked source in %s\n"),
2252 Dir.c_str());
2253 }
2254 else
2255 {
2256 // Call dpkg-source
2257 char S[500];
2258 snprintf(S,sizeof(S),"%s -x %s",
2259 _config->Find("Dir::Bin::dpkg-source","dpkg-source").c_str(),
2260 Dsc[I].Dsc.c_str());
2261 if (system(S) != 0)
2262 {
2263 fprintf(stderr,_("Unpack command '%s' failed.\n"),S);
2264 fprintf(stderr,_("Check if the 'dpkg-dev' package is installed.\n"));
2265 _exit(1);
2266 }
2267 }
2268
2269 // Try to compile it with dpkg-buildpackage
2270 if (_config->FindB("APT::Get::Compile",false) == true)
2271 {
2272 // Call dpkg-buildpackage
2273 char S[500];
2274 snprintf(S,sizeof(S),"cd %s && %s %s",
2275 Dir.c_str(),
2276 _config->Find("Dir::Bin::dpkg-buildpackage","dpkg-buildpackage").c_str(),
2277 _config->Find("DPkg::Build-Options","-b -uc").c_str());
2278
2279 if (system(S) != 0)
2280 {
2281 fprintf(stderr,_("Build command '%s' failed.\n"),S);
2282 _exit(1);
2283 }
2284 }
2285 }
2286
2287 _exit(0);
2288 }
2289
2290 // Wait for the subprocess
2291 int Status = 0;
2292 while (waitpid(Process,&Status,0) != Process)
2293 {
2294 if (errno == EINTR)
2295 continue;
2296 return _error->Errno("waitpid","Couldn't wait for subprocess");
2297 }
2298
2299 if (WIFEXITED(Status) == 0 || WEXITSTATUS(Status) != 0)
2300 return _error->Error(_("Child process failed"));
2301
2302 return true;
2303 }
2304 /*}}}*/
2305 // DoBuildDep - Install/removes packages to satisfy build dependencies /*{{{*/
2306 // ---------------------------------------------------------------------
2307 /* This function will look at the build depends list of the given source
2308 package and install the necessary packages to make it true, or fail. */
2309 bool DoBuildDep(CommandLine &CmdL)
2310 {
2311 CacheFile Cache;
2312 if (Cache.Open(true) == false)
2313 return false;
2314
2315 if (CmdL.FileSize() <= 1)
2316 return _error->Error(_("Must specify at least one package to check builddeps for"));
2317
2318 // Read the source list
2319 pkgSourceList List;
2320 if (List.ReadMainList() == false)
2321 return _error->Error(_("The list of sources could not be read."));
2322
2323 // Create the text record parsers
2324 pkgRecords Recs(Cache);
2325 pkgSrcRecords SrcRecs(List);
2326 if (_error->PendingError() == true)
2327 return false;
2328
2329 // Create the download object
2330 AcqTextStatus Stat(ScreenWidth,_config->FindI("quiet",0));
2331 pkgAcquire Fetcher(&Stat);
2332
2333 unsigned J = 0;
2334 for (const char **I = CmdL.FileList + 1; *I != 0; I++, J++)
2335 {
2336 string Src;
2337 pkgSrcRecords::Parser *Last = FindSrc(*I,Recs,SrcRecs,Src,*Cache);
2338 if (Last == 0)
2339 return _error->Error(_("Unable to find a source package for %s"),Src.c_str());
2340
2341 // Process the build-dependencies
2342 vector<pkgSrcRecords::Parser::BuildDepRec> BuildDeps;
2343 if (Last->BuildDepends(BuildDeps, _config->FindB("APT::Get::Arch-Only",false)) == false)
2344 return _error->Error(_("Unable to get build-dependency information for %s"),Src.c_str());
2345
2346 // Also ensure that build-essential packages are present
2347 Configuration::Item const *Opts = _config->Tree("APT::Build-Essential");
2348 if (Opts)
2349 Opts = Opts->Child;
2350 for (; Opts; Opts = Opts->Next)
2351 {
2352 if (Opts->Value.empty() == true)
2353 continue;
2354
2355 pkgSrcRecords::Parser::BuildDepRec rec;
2356 rec.Package = Opts->Value;
2357 rec.Type = pkgSrcRecords::Parser::BuildDependIndep;
2358 rec.Op = 0;
2359 BuildDeps.push_back(rec);
2360 }
2361
2362 if (BuildDeps.size() == 0)
2363 {
2364 ioprintf(c1out,_("%s has no build depends.\n"),Src.c_str());
2365 continue;
2366 }
2367
2368 // Install the requested packages
2369 unsigned int ExpectedInst = 0;
2370 vector <pkgSrcRecords::Parser::BuildDepRec>::iterator D;
2371 pkgProblemResolver Fix(Cache);
2372 bool skipAlternatives = false; // skip remaining alternatives in an or group
2373 for (D = BuildDeps.begin(); D != BuildDeps.end(); D++)
2374 {
2375 bool hasAlternatives = (((*D).Op & pkgCache::Dep::Or) == pkgCache::Dep::Or);
2376
2377 if (skipAlternatives == true)
2378 {
2379 if (!hasAlternatives)
2380 skipAlternatives = false; // end of or group
2381 continue;
2382 }
2383
2384 if ((*D).Type == pkgSrcRecords::Parser::BuildConflict ||
2385 (*D).Type == pkgSrcRecords::Parser::BuildConflictIndep)
2386 {
2387 pkgCache::PkgIterator Pkg = Cache->FindPkg((*D).Package);
2388 // Build-conflicts on unknown packages are silently ignored
2389 if (Pkg.end() == true)
2390 continue;
2391
2392 pkgCache::VerIterator IV = (*Cache)[Pkg].InstVerIter(*Cache);
2393
2394 /*
2395 * Remove if we have an installed version that satisfies the
2396 * version criteria
2397 */
2398 if (IV.end() == false &&
2399 Cache->VS().CheckDep(IV.VerStr(),(*D).Op,(*D).Version.c_str()) == true)
2400 TryToInstall(Pkg,Cache,Fix,true,false,ExpectedInst);
2401 }
2402 else // BuildDep || BuildDepIndep
2403 {
2404 pkgCache::PkgIterator Pkg = Cache->FindPkg((*D).Package);
2405 if (_config->FindB("Debug::BuildDeps",false) == true)
2406 cout << "Looking for " << (*D).Package << "...\n";
2407
2408 if (Pkg.end() == true)
2409 {
2410 if (_config->FindB("Debug::BuildDeps",false) == true)
2411 cout << " (not found)" << (*D).Package << endl;
2412
2413 if (hasAlternatives)
2414 continue;
2415
2416 return _error->Error(_("%s dependency for %s cannot be satisfied "
2417 "because the package %s cannot be found"),
2418 Last->BuildDepType((*D).Type),Src.c_str(),
2419 (*D).Package.c_str());
2420 }
2421
2422 /*
2423 * if there are alternatives, we've already picked one, so skip
2424 * the rest
2425 *
2426 * TODO: this means that if there's a build-dep on A|B and B is
2427 * installed, we'll still try to install A; more importantly,
2428 * if A is currently broken, we cannot go back and try B. To fix
2429 * this would require we do a Resolve cycle for each package we
2430 * add to the install list. Ugh
2431 */
2432
2433 /*
2434 * If this is a virtual package, we need to check the list of
2435 * packages that provide it and see if any of those are
2436 * installed
2437 */
2438 pkgCache::PrvIterator Prv = Pkg.ProvidesList();
2439 for (; Prv.end() != true; Prv++)
2440 {
2441 if (_config->FindB("Debug::BuildDeps",false) == true)
2442 cout << " Checking provider " << Prv.OwnerPkg().Name() << endl;
2443
2444 if ((*Cache)[Prv.OwnerPkg()].InstVerIter(*Cache).end() == false)
2445 break;
2446 }
2447
2448 // Get installed version and version we are going to install
2449 pkgCache::VerIterator IV = (*Cache)[Pkg].InstVerIter(*Cache);
2450
2451 if ((*D).Version[0] != '\0') {
2452 // Versioned dependency
2453
2454 pkgCache::VerIterator CV = (*Cache)[Pkg].CandidateVerIter(*Cache);
2455
2456 for (; CV.end() != true; CV++)
2457 {
2458 if (Cache->VS().CheckDep(CV.VerStr(),(*D).Op,(*D).Version.c_str()) == true)
2459 break;
2460 }
2461 if (CV.end() == true)
2462 {
2463 if (hasAlternatives)
2464 {
2465 continue;
2466 }
2467 else
2468 {
2469 return _error->Error(_("%s dependency for %s cannot be satisfied "
2470 "because no available versions of package %s "
2471 "can satisfy version requirements"),
2472 Last->BuildDepType((*D).Type),Src.c_str(),
2473 (*D).Package.c_str());
2474 }
2475 }
2476 }
2477 else
2478 {
2479 // Only consider virtual packages if there is no versioned dependency
2480 if (Prv.end() == false)
2481 {
2482 if (_config->FindB("Debug::BuildDeps",false) == true)
2483 cout << " Is provided by installed package " << Prv.OwnerPkg().Name() << endl;
2484 skipAlternatives = hasAlternatives;
2485 continue;
2486 }
2487 }
2488
2489 if (IV.end() == false)
2490 {
2491 if (_config->FindB("Debug::BuildDeps",false) == true)
2492 cout << " Is installed\n";
2493
2494 if (Cache->VS().CheckDep(IV.VerStr(),(*D).Op,(*D).Version.c_str()) == true)
2495 {
2496 skipAlternatives = hasAlternatives;
2497 continue;
2498 }
2499
2500 if (_config->FindB("Debug::BuildDeps",false) == true)
2501 cout << " ...but the installed version doesn't meet the version requirement\n";
2502
2503 if (((*D).Op & pkgCache::Dep::LessEq) == pkgCache::Dep::LessEq)
2504 {
2505 return _error->Error(_("Failed to satisfy %s dependency for %s: Installed package %s is too new"),
2506 Last->BuildDepType((*D).Type),
2507 Src.c_str(),
2508 Pkg.Name());
2509 }
2510 }
2511
2512
2513 if (_config->FindB("Debug::BuildDeps",false) == true)
2514 cout << " Trying to install " << (*D).Package << endl;
2515
2516 if (TryToInstall(Pkg,Cache,Fix,false,false,ExpectedInst) == true)
2517 {
2518 // We successfully installed something; skip remaining alternatives
2519 skipAlternatives = hasAlternatives;
2520 if(_config->FindB("APT::Get::Build-Dep-Automatic", false) == true)
2521 Cache->MarkAuto(Pkg, true);
2522 continue;
2523 }
2524 else if (hasAlternatives)
2525 {
2526 if (_config->FindB("Debug::BuildDeps",false) == true)
2527 cout << " Unsatisfiable, trying alternatives\n";
2528 continue;
2529 }
2530 else
2531 {
2532 return _error->Error(_("Failed to satisfy %s dependency for %s: %s"),
2533 Last->BuildDepType((*D).Type),
2534 Src.c_str(),
2535 (*D).Package.c_str());
2536 }
2537 }
2538 }
2539
2540 Fix.InstallProtect();
2541 if (Fix.Resolve(true) == false)
2542 _error->Discard();
2543
2544 // Now we check the state of the packages,
2545 if (Cache->BrokenCount() != 0)
2546 return _error->Error(_("Build-dependencies for %s could not be satisfied."),*I);
2547 }
2548
2549 if (InstallPackages(Cache, false, true) == false)
2550 return _error->Error(_("Failed to process build dependencies"));
2551 return true;
2552 }
2553 /*}}}*/
2554
2555 // DoMoo - Never Ask, Never Tell /*{{{*/
2556 // ---------------------------------------------------------------------
2557 /* */
2558 bool DoMoo(CommandLine &CmdL)
2559 {
2560 cout <<
2561 " (__) \n"
2562 " (oo) \n"
2563 " /------\\/ \n"
2564 " / | || \n"
2565 " * /\\---/\\ \n"
2566 " ~~ ~~ \n"
2567 "....\"Have you mooed today?\"...\n";
2568
2569 return true;
2570 }
2571 /*}}}*/
2572 // ShowHelp - Show a help screen /*{{{*/
2573 // ---------------------------------------------------------------------
2574 /* */
2575 bool ShowHelp(CommandLine &CmdL)
2576 {
2577 ioprintf(cout,_("%s %s for %s compiled on %s %s\n"),PACKAGE,VERSION,
2578 COMMON_ARCH,__DATE__,__TIME__);
2579
2580 if (_config->FindB("version") == true)
2581 {
2582 cout << _("Supported modules:") << endl;
2583
2584 for (unsigned I = 0; I != pkgVersioningSystem::GlobalListLen; I++)
2585 {
2586 pkgVersioningSystem *VS = pkgVersioningSystem::GlobalList[I];
2587 if (_system != 0 && _system->VS == VS)
2588 cout << '*';
2589 else
2590 cout << ' ';
2591 cout << "Ver: " << VS->Label << endl;
2592
2593 /* Print out all the packaging systems that will work with
2594 this VS */
2595 for (unsigned J = 0; J != pkgSystem::GlobalListLen; J++)
2596 {
2597 pkgSystem *Sys = pkgSystem::GlobalList[J];
2598 if (_system == Sys)
2599 cout << '*';
2600 else
2601 cout << ' ';
2602 if (Sys->VS->TestCompatibility(*VS) == true)
2603 cout << "Pkg: " << Sys->Label << " (Priority " << Sys->Score(*_config) << ")" << endl;
2604 }
2605 }
2606
2607 for (unsigned I = 0; I != pkgSourceList::Type::GlobalListLen; I++)
2608 {
2609 pkgSourceList::Type *Type = pkgSourceList::Type::GlobalList[I];
2610 cout << " S.L: '" << Type->Name << "' " << Type->Label << endl;
2611 }
2612
2613 for (unsigned I = 0; I != pkgIndexFile::Type::GlobalListLen; I++)
2614 {
2615 pkgIndexFile::Type *Type = pkgIndexFile::Type::GlobalList[I];
2616 cout << " Idx: " << Type->Label << endl;
2617 }
2618
2619 return true;
2620 }
2621
2622 cout <<
2623 _("Usage: apt-get [options] command\n"
2624 " apt-get [options] install|remove pkg1 [pkg2 ...]\n"
2625 " apt-get [options] source pkg1 [pkg2 ...]\n"
2626 "\n"
2627 "apt-get is a simple command line interface for downloading and\n"
2628 "installing packages. The most frequently used commands are update\n"
2629 "and install.\n"
2630 "\n"
2631 "Commands:\n"
2632 " update - Retrieve new lists of packages\n"
2633 " upgrade - Perform an upgrade\n"
2634 " install - Install new packages (pkg is libc6 not libc6.deb)\n"
2635 " remove - Remove packages\n"
2636 " autoremove - Remove automatically all unused packages\n"
2637 " purge - Remove and purge packages\n"
2638 " source - Download source archives\n"
2639 " build-dep - Configure build-dependencies for source packages\n"
2640 " dist-upgrade - Distribution upgrade, see apt-get(8)\n"
2641 " dselect-upgrade - Follow dselect selections\n"
2642 " clean - Erase downloaded archive files\n"
2643 " autoclean - Erase old downloaded archive files\n"
2644 " check - Verify that there are no broken dependencies\n"
2645 "\n"
2646 "Options:\n"
2647 " -h This help text.\n"
2648 " -q Loggable output - no progress indicator\n"
2649 " -qq No output except for errors\n"
2650 " -d Download only - do NOT install or unpack archives\n"
2651 " -s No-act. Perform ordering simulation\n"
2652 " -y Assume Yes to all queries and do not prompt\n"
2653 " -f Attempt to correct a system with broken dependencies in place\n"
2654 " -m Attempt to continue if archives are unlocatable\n"
2655 " -u Show a list of upgraded packages as well\n"
2656 " -b Build the source package after fetching it\n"
2657 " -V Show verbose version numbers\n"
2658 " -c=? Read this configuration file\n"
2659 " -o=? Set an arbitrary configuration option, eg -o dir::cache=/tmp\n"
2660 "See the apt-get(8), sources.list(5) and apt.conf(5) manual\n"
2661 "pages for more information and options.\n"
2662 " This APT has Super Cow Powers.\n");
2663 return true;
2664 }
2665 /*}}}*/
2666 // GetInitialize - Initialize things for apt-get /*{{{*/
2667 // ---------------------------------------------------------------------
2668 /* */
2669 void GetInitialize()
2670 {
2671 _config->Set("quiet",0);
2672 _config->Set("help",false);
2673 _config->Set("APT::Get::Download-Only",false);
2674 _config->Set("APT::Get::Simulate",false);
2675 _config->Set("APT::Get::Assume-Yes",false);
2676 _config->Set("APT::Get::Fix-Broken",false);
2677 _config->Set("APT::Get::Force-Yes",false);
2678 _config->Set("APT::Get::List-Cleanup",true);
2679 _config->Set("APT::Get::AutomaticRemove",false);
2680 }
2681 /*}}}*/
2682 // SigWinch - Window size change signal handler /*{{{*/
2683 // ---------------------------------------------------------------------
2684 /* */
2685 void SigWinch(int)
2686 {
2687 // Riped from GNU ls
2688 #ifdef TIOCGWINSZ
2689 struct winsize ws;
2690
2691 if (ioctl(1, TIOCGWINSZ, &ws) != -1 && ws.ws_col >= 5)
2692 ScreenWidth = ws.ws_col - 1;
2693 #endif
2694 }
2695 /*}}}*/
2696
2697 int main(int argc,const char *argv[])
2698 {
2699 CommandLine::Args Args[] = {
2700 {'h',"help","help",0},
2701 {'v',"version","version",0},
2702 {'V',"verbose-versions","APT::Get::Show-Versions",0},
2703 {'q',"quiet","quiet",CommandLine::IntLevel},
2704 {'q',"silent","quiet",CommandLine::IntLevel},
2705 {'d',"download-only","APT::Get::Download-Only",0},
2706 {'b',"compile","APT::Get::Compile",0},
2707 {'b',"build","APT::Get::Compile",0},
2708 {'s',"simulate","APT::Get::Simulate",0},
2709 {'s',"just-print","APT::Get::Simulate",0},
2710 {'s',"recon","APT::Get::Simulate",0},
2711 {'s',"dry-run","APT::Get::Simulate",0},
2712 {'s',"no-act","APT::Get::Simulate",0},
2713 {'y',"yes","APT::Get::Assume-Yes",0},
2714 {'y',"assume-yes","APT::Get::Assume-Yes",0},
2715 {'f',"fix-broken","APT::Get::Fix-Broken",0},
2716 {'u',"show-upgraded","APT::Get::Show-Upgraded",0},
2717 {'m',"ignore-missing","APT::Get::Fix-Missing",0},
2718 {'t',"target-release","APT::Default-Release",CommandLine::HasArg},
2719 {'t',"default-release","APT::Default-Release",CommandLine::HasArg},
2720 {0,"download","APT::Get::Download",0},
2721 {0,"fix-missing","APT::Get::Fix-Missing",0},
2722 {0,"ignore-hold","APT::Ignore-Hold",0},
2723 {0,"upgrade","APT::Get::upgrade",0},
2724 {0,"force-yes","APT::Get::force-yes",0},
2725 {0,"print-uris","APT::Get::Print-URIs",0},
2726 {0,"diff-only","APT::Get::Diff-Only",0},
2727 {0,"tar-only","APT::Get::Tar-Only",0},
2728 {0,"dsc-only","APT::Get::Dsc-Only",0},
2729 {0,"purge","APT::Get::Purge",0},
2730 {0,"list-cleanup","APT::Get::List-Cleanup",0},
2731 {0,"reinstall","APT::Get::ReInstall",0},
2732 {0,"trivial-only","APT::Get::Trivial-Only",0},
2733 {0,"remove","APT::Get::Remove",0},
2734 {0,"only-source","APT::Get::Only-Source",0},
2735 {0,"arch-only","APT::Get::Arch-Only",0},
2736 {0,"auto-remove","APT::Get::AutomaticRemove",0},
2737 {0,"allow-unauthenticated","APT::Get::AllowUnauthenticated",0},
2738 {0,"install-recommends","APT::Install-Recommends",CommandLine::Boolean},
2739 {0,"fix-policy","APT::Get::Fix-Policy-Broken",0},
2740 {'c',"config-file",0,CommandLine::ConfigFile},
2741 {'o',"option",0,CommandLine::ArbItem},
2742 {0,0,0,0}};
2743 CommandLine::Dispatch Cmds[] = {{"update",&DoUpdate},
2744 {"upgrade",&DoUpgrade},
2745 {"install",&DoInstall},
2746 {"remove",&DoInstall},
2747 {"purge",&DoInstall},
2748 {"autoremove",&DoInstall},
2749 {"purge",&DoInstall},
2750 {"dist-upgrade",&DoDistUpgrade},
2751 {"dselect-upgrade",&DoDSelectUpgrade},
2752 {"build-dep",&DoBuildDep},
2753 {"clean",&DoClean},
2754 {"autoclean",&DoAutoClean},
2755 {"check",&DoCheck},
2756 {"source",&DoSource},
2757 {"moo",&DoMoo},
2758 {"help",&ShowHelp},
2759 {0,0}};
2760
2761 // Set up gettext support
2762 setlocale(LC_ALL,"");
2763 textdomain(PACKAGE);
2764
2765 // Parse the command line and initialize the package library
2766 CommandLine CmdL(Args,_config);
2767 if (pkgInitConfig(*_config) == false ||
2768 CmdL.Parse(argc,argv) == false ||
2769 pkgInitSystem(*_config,_system) == false)
2770 {
2771 if (_config->FindB("version") == true)
2772 ShowHelp(CmdL);
2773
2774 _error->DumpErrors();
2775 return 100;
2776 }
2777
2778 // See if the help should be shown
2779 if (_config->FindB("help") == true ||
2780 _config->FindB("version") == true ||
2781 CmdL.FileSize() == 0)
2782 {
2783 ShowHelp(CmdL);
2784 return 0;
2785 }
2786
2787 // Deal with stdout not being a tty
2788 if (!isatty(STDOUT_FILENO) && _config->FindI("quiet",0) < 1)
2789 _config->Set("quiet","1");
2790
2791 ofstream devnull;
2792 devnull.open("/dev/null");
2793
2794 // Setup the output streams
2795 c0out.rdbuf(cout.rdbuf());
2796 c1out.rdbuf(cout.rdbuf());
2797 c2out.rdbuf(cout.rdbuf());
2798 if (_config->FindI("quiet",0) > 0)
2799 c0out.rdbuf(devnull.rdbuf());
2800 if (_config->FindI("quiet",0) > 1)
2801 c1out.rdbuf(devnull.rdbuf());
2802
2803 // Setup the signals
2804 signal(SIGPIPE,SIG_IGN);
2805 signal(SIGWINCH,SigWinch);
2806 SigWinch(0);
2807
2808 // Match the operation
2809 CmdL.DispatchArg(Cmds);
2810
2811 // Print any errors or warnings found during parsing
2812 if (_error->empty() == false)
2813 {
2814 bool Errors = _error->PendingError();
2815 _error->DumpErrors();
2816 return Errors == true?100:0;
2817 }
2818
2819 return 0;
2820 }