Floating point error. Bug #64394
[ntk/apt.git] / cmdline / apt-get.cc
CommitLineData
5ec427c2
AL
1// -*- mode: cpp; mode: fold -*-
2// Description /*{{{*/
d82d6873 3// $Id: apt-get.cc,v 1.98 2000/05/14 06:01:04 jgg Exp $
5ec427c2
AL
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 /*{{{*/
0a8e3465
AL
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>
0a8e3465 33#include <apt-pkg/algorithms.h>
0919e3f9 34#include <apt-pkg/acquire-item.h>
03e39e59 35#include <apt-pkg/dpkgpm.h>
cdcc6d34 36#include <apt-pkg/strutl.h>
1bc849af 37#include <apt-pkg/clean.h>
36375005
AL
38#include <apt-pkg/srcrecords.h>
39#include <apt-pkg/version.h>
2d11135a 40#include <apt-pkg/cachefile.h>
0a8e3465
AL
41
42#include <config.h>
43
0919e3f9
AL
44#include "acqprogress.h"
45
0a8e3465 46#include <fstream.h>
d7827aca
AL
47#include <termios.h>
48#include <sys/ioctl.h>
1bc849af 49#include <sys/stat.h>
101030ab 50#include <sys/statvfs.h>
d7827aca 51#include <signal.h>
65a1e968 52#include <unistd.h>
3e3221ba 53#include <stdio.h>
d6e79b75 54#include <errno.h>
c373c37a 55#include <regex.h>
54676e1a 56#include <sys/wait.h>
0a8e3465
AL
57 /*}}}*/
58
59ostream c0out;
60ostream c1out;
61ostream c2out;
62ofstream devnull("/dev/null");
63unsigned int ScreenWidth = 80;
64
1089ca89
AL
65// class CacheFile - Cover class for some dependency cache functions /*{{{*/
66// ---------------------------------------------------------------------
67/* */
68class CacheFile : public pkgCacheFile
69{
70 static pkgCache *SortCache;
71 static int NameComp(const void *a,const void *b);
72
73 public:
74 pkgCache::Package **List;
75
76 void Sort();
77 bool CheckDeps(bool AllowBroken = false);
78 bool Open(bool WithLock = true)
79 {
80 OpTextProgress Prog(*_config);
81 if (pkgCacheFile::Open(Prog,WithLock) == false)
82 return false;
83 Sort();
84 return true;
85 };
86 CacheFile() : List(0) {};
87};
88 /*}}}*/
89
a6568219
AL
90// YnPrompt - Yes No Prompt. /*{{{*/
91// ---------------------------------------------------------------------
92/* Returns true on a Yes.*/
93bool YnPrompt()
94{
95 if (_config->FindB("APT::Get::Assume-Yes",false) == true)
96 {
738309d6 97 c1out << 'Y' << endl;
a6568219
AL
98 return true;
99 }
100
101 char C = 0;
102 char Jnk = 0;
103 read(STDIN_FILENO,&C,1);
104 while (C != '\n' && Jnk != '\n') read(STDIN_FILENO,&Jnk,1);
105
106 if (!(C == 'Y' || C == 'y' || C == '\n' || C == '\r'))
107 return false;
108 return true;
109}
110 /*}}}*/
6f86c974
AL
111// AnalPrompt - Annoying Yes No Prompt. /*{{{*/
112// ---------------------------------------------------------------------
113/* Returns true on a Yes.*/
114bool AnalPrompt(const char *Text)
115{
116 char Buf[1024];
117 cin.getline(Buf,sizeof(Buf));
118 if (strcmp(Buf,Text) == 0)
119 return true;
120 return false;
121}
122 /*}}}*/
0a8e3465
AL
123// ShowList - Show a list /*{{{*/
124// ---------------------------------------------------------------------
125/* This prints out a string of space seperated words with a title and
126 a two space indent line wraped to the current screen width. */
83d89a9f 127bool ShowList(ostream &out,string Title,string List)
0a8e3465
AL
128{
129 if (List.empty() == true)
83d89a9f 130 return true;
0a8e3465
AL
131
132 // Acount for the leading space
133 int ScreenWidth = ::ScreenWidth - 3;
134
135 out << Title << endl;
136 string::size_type Start = 0;
137 while (Start < List.size())
138 {
139 string::size_type End;
140 if (Start + ScreenWidth >= List.size())
141 End = List.size();
142 else
143 End = List.rfind(' ',Start+ScreenWidth);
144
145 if (End == string::npos || End < Start)
146 End = Start + ScreenWidth;
147 out << " " << string(List,Start,End - Start) << endl;
148 Start = End + 1;
149 }
83d89a9f 150 return false;
0a8e3465
AL
151}
152 /*}}}*/
153// ShowBroken - Debugging aide /*{{{*/
154// ---------------------------------------------------------------------
155/* This prints out the names of all the packages that are broken along
156 with the name of each each broken dependency and a quite version
157 description. */
421c8d10 158void ShowBroken(ostream &out,CacheFile &Cache,bool Now)
0a8e3465 159{
30e1eab5 160 out << "Sorry, but the following packages have unmet dependencies:" << endl;
1089ca89 161 for (unsigned J = 0; J < Cache->Head().PackageCount; J++)
0a8e3465 162 {
1089ca89
AL
163 pkgCache::PkgIterator I(Cache,Cache.List[J]);
164
303a1703
AL
165 if (Cache[I].InstBroken() == false)
166 continue;
167
168 // Print out each package and the failed dependencies
169 out <<" " << I.Name() << ":";
648e3cb4 170 unsigned Indent = strlen(I.Name()) + 3;
303a1703
AL
171 bool First = true;
172 if (Cache[I].InstVerIter(Cache).end() == true)
0a8e3465 173 {
303a1703
AL
174 cout << endl;
175 continue;
176 }
177
30e1eab5 178 for (pkgCache::DepIterator D = Cache[I].InstVerIter(Cache).DependsList(); D.end() == false;)
303a1703 179 {
30e1eab5
AL
180 // Compute a single dependency element (glob or)
181 pkgCache::DepIterator Start;
182 pkgCache::DepIterator End;
183 D.GlobOr(Start,End);
76fbce56 184
1089ca89 185 if (Cache->IsImportantDep(End) == false ||
30e1eab5 186 (Cache[End] & pkgDepCache::DepGInstall) == pkgDepCache::DepGInstall)
303a1703 187 continue;
cc718e9a 188
648e3cb4
AL
189 bool FirstOr = true;
190 while (1)
0a8e3465 191 {
648e3cb4
AL
192 if (First == false)
193 for (unsigned J = 0; J != Indent; J++)
194 out << ' ';
195 First = false;
196
197 if (FirstOr == false)
198 {
199 for (unsigned J = 0; J != strlen(End.DepType()) + 3; J++)
200 out << ' ';
201 }
0a8e3465 202 else
648e3cb4
AL
203 out << ' ' << End.DepType() << ": ";
204 FirstOr = false;
205
206 out << Start.TargetPkg().Name();
207
208 // Show a quick summary of the version requirements
209 if (Start.TargetVer() != 0)
210 out << " (" << Start.CompType() << " " << Start.TargetVer() <<
211 ")";
212
213 /* Show a summary of the target package if possible. In the case
214 of virtual packages we show nothing */
215 pkgCache::PkgIterator Targ = Start.TargetPkg();
216 if (Targ->ProvidesList == 0)
7e798dd7 217 {
648e3cb4
AL
218 out << " but ";
219 pkgCache::VerIterator Ver = Cache[Targ].InstVerIter(Cache);
220 if (Ver.end() == false)
221 out << Ver.VerStr() << (Now?" is installed":" is to be installed");
222 else
303a1703 223 {
648e3cb4
AL
224 if (Cache[Targ].CandidateVerIter(Cache).end() == true)
225 {
226 if (Targ->ProvidesList == 0)
227 out << "it is not installable";
228 else
229 out << "it is a virtual package";
230 }
303a1703 231 else
648e3cb4
AL
232 out << (Now?"it is not installed":"it is not going to be installed");
233 }
234 }
235
236 if (Start != End)
237 cout << " or";
238 out << endl;
239
240 if (Start == End)
241 break;
242 Start++;
243 }
303a1703 244 }
0a8e3465
AL
245 }
246}
247 /*}}}*/
248// ShowNew - Show packages to newly install /*{{{*/
249// ---------------------------------------------------------------------
250/* */
1089ca89 251void ShowNew(ostream &out,CacheFile &Cache)
0a8e3465
AL
252{
253 /* Print out a list of packages that are going to be removed extra
254 to what the user asked */
0a8e3465 255 string List;
1089ca89
AL
256 for (unsigned J = 0; J < Cache->Head().PackageCount; J++)
257 {
258 pkgCache::PkgIterator I(Cache,Cache.List[J]);
259 if (Cache[I].NewInstall() == true)
0a8e3465 260 List += string(I.Name()) + " ";
1089ca89
AL
261 }
262
0a8e3465
AL
263 ShowList(out,"The following NEW packages will be installed:",List);
264}
265 /*}}}*/
266// ShowDel - Show packages to delete /*{{{*/
267// ---------------------------------------------------------------------
268/* */
1089ca89 269void ShowDel(ostream &out,CacheFile &Cache)
0a8e3465
AL
270{
271 /* Print out a list of packages that are going to be removed extra
272 to what the user asked */
0a8e3465 273 string List;
1089ca89 274 for (unsigned J = 0; J < Cache->Head().PackageCount; J++)
fc4b5c9f 275 {
1089ca89
AL
276 pkgCache::PkgIterator I(Cache,Cache.List[J]);
277 if (Cache[I].Delete() == true)
fc4b5c9f 278 {
1089ca89 279 if ((Cache[I].iFlags & pkgDepCache::Purge) == pkgDepCache::Purge)
fc4b5c9f
AL
280 List += string(I.Name()) + "* ";
281 else
282 List += string(I.Name()) + " ";
283 }
284 }
3d615484 285
0a8e3465
AL
286 ShowList(out,"The following packages will be REMOVED:",List);
287}
288 /*}}}*/
289// ShowKept - Show kept packages /*{{{*/
290// ---------------------------------------------------------------------
291/* */
f292686b 292void ShowKept(ostream &out,CacheFile &Cache)
0a8e3465 293{
0a8e3465 294 string List;
f292686b 295 for (unsigned J = 0; J < Cache->Head().PackageCount; J++)
0a8e3465 296 {
f292686b
AL
297 pkgCache::PkgIterator I(Cache,Cache.List[J]);
298
0a8e3465 299 // Not interesting
f292686b
AL
300 if (Cache[I].Upgrade() == true || Cache[I].Upgradable() == false ||
301 I->CurrentVer == 0 || Cache[I].Delete() == true)
0a8e3465
AL
302 continue;
303
304 List += string(I.Name()) + " ";
305 }
306 ShowList(out,"The following packages have been kept back",List);
307}
308 /*}}}*/
309// ShowUpgraded - Show upgraded packages /*{{{*/
310// ---------------------------------------------------------------------
311/* */
1089ca89 312void ShowUpgraded(ostream &out,CacheFile &Cache)
0a8e3465 313{
0a8e3465 314 string List;
1089ca89 315 for (unsigned J = 0; J < Cache->Head().PackageCount; J++)
0a8e3465 316 {
1089ca89
AL
317 pkgCache::PkgIterator I(Cache,Cache.List[J]);
318
0a8e3465 319 // Not interesting
1089ca89 320 if (Cache[I].Upgrade() == false || Cache[I].NewInstall() == true)
0a8e3465
AL
321 continue;
322
323 List += string(I.Name()) + " ";
324 }
325 ShowList(out,"The following packages will be upgraded",List);
326}
327 /*}}}*/
328// ShowHold - Show held but changed packages /*{{{*/
329// ---------------------------------------------------------------------
330/* */
1089ca89 331bool ShowHold(ostream &out,CacheFile &Cache)
0a8e3465 332{
0a8e3465 333 string List;
1089ca89 334 for (unsigned J = 0; J < Cache->Head().PackageCount; J++)
0a8e3465 335 {
1089ca89
AL
336 pkgCache::PkgIterator I(Cache,Cache.List[J]);
337 if (Cache[I].InstallVer != (pkgCache::Version *)I.CurrentVer() &&
0a8e3465
AL
338 I->SelectedState == pkgCache::State::Hold)
339 List += string(I.Name()) + " ";
340 }
341
83d89a9f 342 return ShowList(out,"The following held packages will be changed:",List);
0a8e3465
AL
343}
344 /*}}}*/
345// ShowEssential - Show an essential package warning /*{{{*/
346// ---------------------------------------------------------------------
347/* This prints out a warning message that is not to be ignored. It shows
348 all essential packages and their dependents that are to be removed.
349 It is insanely risky to remove the dependents of an essential package! */
1089ca89 350bool ShowEssential(ostream &out,CacheFile &Cache)
0a8e3465 351{
0a8e3465 352 string List;
1089ca89
AL
353 bool *Added = new bool[Cache->HeaderP->PackageCount];
354 for (unsigned int I = 0; I != Cache->HeaderP->PackageCount; I++)
0a8e3465
AL
355 Added[I] = false;
356
1089ca89 357 for (unsigned J = 0; J < Cache->Head().PackageCount; J++)
0a8e3465 358 {
1089ca89 359 pkgCache::PkgIterator I(Cache,Cache.List[J]);
0a8e3465
AL
360 if ((I->Flags & pkgCache::Flag::Essential) != pkgCache::Flag::Essential)
361 continue;
362
363 // The essential package is being removed
1089ca89 364 if (Cache[I].Delete() == true)
0a8e3465
AL
365 {
366 if (Added[I->ID] == false)
367 {
368 Added[I->ID] = true;
369 List += string(I.Name()) + " ";
370 }
371 }
372
373 if (I->CurrentVer == 0)
374 continue;
375
376 // Print out any essential package depenendents that are to be removed
377 for (pkgDepCache::DepIterator D = I.CurrentVer().DependsList(); D.end() == false; D++)
378 {
3e3221ba
AL
379 // Skip everything but depends
380 if (D->Type != pkgCache::Dep::PreDepends &&
381 D->Type != pkgCache::Dep::Depends)
382 continue;
383
0a8e3465 384 pkgCache::PkgIterator P = D.SmartTargetPkg();
1089ca89 385 if (Cache[P].Delete() == true)
0a8e3465
AL
386 {
387 if (Added[P->ID] == true)
388 continue;
389 Added[P->ID] = true;
3e3221ba
AL
390
391 char S[300];
392 sprintf(S,"%s (due to %s) ",P.Name(),I.Name());
393 List += S;
0a8e3465
AL
394 }
395 }
396 }
397
83d89a9f 398 delete [] Added;
0a8e3465
AL
399 if (List.empty() == false)
400 out << "WARNING: The following essential packages will be removed" << endl;
83d89a9f 401 return ShowList(out,"This should NOT be done unless you know exactly what you are doing!",List);
0a8e3465
AL
402}
403 /*}}}*/
404// Stats - Show some statistics /*{{{*/
405// ---------------------------------------------------------------------
406/* */
407void Stats(ostream &out,pkgDepCache &Dep)
408{
409 unsigned long Upgrade = 0;
410 unsigned long Install = 0;
d0c59649 411 unsigned long ReInstall = 0;
0a8e3465
AL
412 for (pkgCache::PkgIterator I = Dep.PkgBegin(); I.end() == false; I++)
413 {
414 if (Dep[I].NewInstall() == true)
415 Install++;
416 else
417 if (Dep[I].Upgrade() == true)
418 Upgrade++;
d0c59649
AL
419 if (Dep[I].Delete() == false && (Dep[I].iFlags & pkgDepCache::ReInstall) == pkgDepCache::ReInstall)
420 ReInstall++;
0a8e3465
AL
421 }
422
423 out << Upgrade << " packages upgraded, " <<
d0c59649
AL
424 Install << " newly installed, ";
425 if (ReInstall != 0)
426 out << ReInstall << " reinstalled, ";
427 out << Dep.DelCount() << " to remove and " <<
0a8e3465
AL
428 Dep.KeepCount() << " not upgraded." << endl;
429
430 if (Dep.BadCount() != 0)
431 out << Dep.BadCount() << " packages not fully installed or removed." << endl;
432}
433 /*}}}*/
434
1089ca89 435// CacheFile::NameComp - QSort compare by name /*{{{*/
0a8e3465
AL
436// ---------------------------------------------------------------------
437/* */
1089ca89
AL
438pkgCache *CacheFile::SortCache = 0;
439int CacheFile::NameComp(const void *a,const void *b)
0a8e3465 440{
8508b1df
AL
441 if (*(pkgCache::Package **)a == 0 || *(pkgCache::Package **)b == 0)
442 return *(pkgCache::Package **)a - *(pkgCache::Package **)b;
0a8e3465 443
1089ca89
AL
444 const pkgCache::Package &A = **(pkgCache::Package **)a;
445 const pkgCache::Package &B = **(pkgCache::Package **)b;
446
447 return strcmp(SortCache->StrP + A.Name,SortCache->StrP + B.Name);
448}
449 /*}}}*/
450// CacheFile::Sort - Sort by name /*{{{*/
451// ---------------------------------------------------------------------
452/* */
453void CacheFile::Sort()
454{
455 delete [] List;
456 List = new pkgCache::Package *[Cache->Head().PackageCount];
457 memset(List,0,sizeof(*List)*Cache->Head().PackageCount);
458 pkgCache::PkgIterator I = Cache->PkgBegin();
459 for (;I.end() != true; I++)
460 List[I->ID] = I;
461
462 SortCache = *this;
463 qsort(List,Cache->Head().PackageCount,sizeof(*List),NameComp);
464}
0a8e3465
AL
465 /*}}}*/
466// CacheFile::Open - Open the cache file /*{{{*/
467// ---------------------------------------------------------------------
468/* This routine generates the caches and then opens the dependency cache
469 and verifies that the system is OK. */
2d11135a 470bool CacheFile::CheckDeps(bool AllowBroken)
0a8e3465 471{
d38b7b3d
AL
472 if (_error->PendingError() == true)
473 return false;
0a8e3465 474
0a8e3465
AL
475 // Check that the system is OK
476 if (Cache->DelCount() != 0 || Cache->InstCount() != 0)
477 return _error->Error("Internal Error, non-zero counts");
478
479 // Apply corrections for half-installed packages
480 if (pkgApplyStatus(*Cache) == false)
481 return false;
482
483 // Nothing is broken
7c57fe64 484 if (Cache->BrokenCount() == 0 || AllowBroken == true)
0a8e3465
AL
485 return true;
486
487 // Attempt to fix broken things
488 if (_config->FindB("APT::Get::Fix-Broken",false) == true)
489 {
490 c1out << "Correcting dependencies..." << flush;
491 if (pkgFixBroken(*Cache) == false || Cache->BrokenCount() != 0)
492 {
493 c1out << " failed." << endl;
421c8d10 494 ShowBroken(c1out,*this,true);
0a8e3465
AL
495
496 return _error->Error("Unable to correct dependencies");
497 }
7e798dd7
AL
498 if (pkgMinimizeUpgrade(*Cache) == false)
499 return _error->Error("Unable to minimize the upgrade set");
0a8e3465
AL
500
501 c1out << " Done" << endl;
502 }
503 else
504 {
505 c1out << "You might want to run `apt-get -f install' to correct these." << endl;
421c8d10 506 ShowBroken(c1out,*this,true);
0a8e3465
AL
507
508 return _error->Error("Unmet dependencies. Try using -f.");
509 }
510
511 return true;
512}
513 /*}}}*/
514
515// InstallPackages - Actually download and install the packages /*{{{*/
516// ---------------------------------------------------------------------
517/* This displays the informative messages describing what is going to
518 happen and then calls the download routines */
a3eaf954
AL
519bool InstallPackages(CacheFile &Cache,bool ShwKept,bool Ask = true,
520 bool Saftey = true)
0a8e3465 521{
fc4b5c9f
AL
522 if (_config->FindB("APT::Get::Purge",false) == true)
523 {
524 pkgCache::PkgIterator I = Cache->PkgBegin();
525 for (; I.end() == false; I++)
d556d1a1
AL
526 {
527 if (I.Purge() == false && Cache[I].Mode == pkgDepCache::ModeDelete)
528 Cache->MarkDelete(I,true);
529 }
fc4b5c9f
AL
530 }
531
83d89a9f 532 bool Fail = false;
6f86c974 533 bool Essential = false;
83d89a9f 534
a6568219 535 // Show all the various warning indicators
0a8e3465
AL
536 ShowDel(c1out,Cache);
537 ShowNew(c1out,Cache);
538 if (ShwKept == true)
539 ShowKept(c1out,Cache);
7a215bee 540 Fail |= !ShowHold(c1out,Cache);
0a8e3465
AL
541 if (_config->FindB("APT::Get::Show-Upgraded",false) == true)
542 ShowUpgraded(c1out,Cache);
6f86c974
AL
543 Essential = !ShowEssential(c1out,Cache);
544 Fail |= Essential;
0a8e3465
AL
545 Stats(c1out,Cache);
546
547 // Sanity check
d38b7b3d 548 if (Cache->BrokenCount() != 0)
0a8e3465 549 {
421c8d10 550 ShowBroken(c1out,Cache,false);
0a8e3465
AL
551 return _error->Error("Internal Error, InstallPackages was called with broken packages!");
552 }
553
d0c59649 554 if (Cache->DelCount() == 0 && Cache->InstCount() == 0 &&
d38b7b3d 555 Cache->BadCount() == 0)
c60d151b 556 return true;
03e39e59 557
d150b09d
AL
558 // No remove flag
559 if (Cache->DelCount() != 0 && _config->FindB("APT::Get::No-Remove",false) == true)
560 return _error->Error("Packages need to be removed but No Remove was specified.");
561
03e39e59
AL
562 // Run the simulator ..
563 if (_config->FindB("APT::Get::Simulate") == true)
564 {
565 pkgSimulate PM(Cache);
281daf46
AL
566 pkgPackageManager::OrderResult Res = PM.DoInstall();
567 if (Res == pkgPackageManager::Failed)
568 return false;
569 if (Res != pkgPackageManager::Completed)
570 return _error->Error("Internal Error, Ordering didn't finish");
571 return true;
03e39e59
AL
572 }
573
574 // Create the text record parser
575 pkgRecords Recs(Cache);
83d89a9f
AL
576 if (_error->PendingError() == true)
577 return false;
578
d38b7b3d 579 // Lock the archive directory
36375005 580 FileFd Lock;
d38b7b3d
AL
581 if (_config->FindB("Debug::NoLocking",false) == false)
582 {
36375005 583 Lock.Fd(GetLock(_config->FindDir("Dir::Cache::Archives") + "lock"));
d38b7b3d
AL
584 if (_error->PendingError() == true)
585 return _error->Error("Unable to lock the download directory");
586 }
03e39e59
AL
587
588 // Create the download object
589 AcqTextStatus Stat(ScreenWidth,_config->FindI("quiet",0));
590 pkgAcquire Fetcher(&Stat);
591
592 // Read the source list
593 pkgSourceList List;
594 if (List.ReadMainList() == false)
595 return _error->Error("The list of sources could not be read.");
596
597 // Create the package manager and prepare to download
30e1eab5 598 pkgDPkgPM PM(Cache);
424c3bc0
AL
599 if (PM.GetArchives(&Fetcher,&List,&Recs) == false ||
600 _error->PendingError() == true)
03e39e59
AL
601 return false;
602
7a1b1f8b 603 // Display statistics
a6568219 604 unsigned long FetchBytes = Fetcher.FetchNeeded();
6b1ff003 605 unsigned long FetchPBytes = Fetcher.PartialPresent();
a6568219 606 unsigned long DebBytes = Fetcher.TotalNeeded();
d38b7b3d
AL
607 if (DebBytes != Cache->DebSize())
608 {
609 c0out << DebBytes << ',' << Cache->DebSize() << endl;
a6568219 610 c0out << "How odd.. The sizes didn't match, email apt@packages.debian.org" << endl;
d38b7b3d 611 }
138d4b3d 612
7a1b1f8b 613 // Number of bytes
fc9d4b7b 614 c1out << "Need to get ";
a6568219 615 if (DebBytes != FetchBytes)
314037ba 616 c1out << SizeToStr(FetchBytes) << "B/" << SizeToStr(DebBytes) << 'B';
a6568219 617 else
314037ba 618 c1out << SizeToStr(DebBytes) << 'B';
a6568219
AL
619
620 c1out << " of archives. After unpacking ";
10bb1f5f
AL
621
622 // Size delta
623 if (Cache->UsrSize() >= 0)
624 c1out << SizeToStr(Cache->UsrSize()) << "B will be used." << endl;
625 else
626 c1out << SizeToStr(-1*Cache->UsrSize()) << "B will be freed." << endl;
627
628 if (_error->PendingError() == true)
629 return false;
31a0531d 630
01b64152
AL
631 /* Check for enough free space, but only if we are actually going to
632 download */
633 if (_config->FindB("APT::Get::Print-URIs") == false)
634 {
635 struct statvfs Buf;
636 string OutputDir = _config->FindDir("Dir::Cache::Archives");
637 if (statvfs(OutputDir.c_str(),&Buf) != 0)
638 return _error->Errno("statvfs","Couldn't determine free space in %s",
639 OutputDir.c_str());
640 if (unsigned(Buf.f_bfree) < (FetchBytes - FetchPBytes)/Buf.f_bsize)
641 return _error->Error("Sorry, you don't have enough free space in %s to hold all the .debs.",
642 OutputDir.c_str());
643 }
644
83d89a9f 645 // Fail safe check
0c95c765
AL
646 if (_config->FindI("quiet",0) >= 2 ||
647 _config->FindB("APT::Get::Assume-Yes",false) == true)
83d89a9f
AL
648 {
649 if (Fail == true && _config->FindB("APT::Get::Force-Yes",false) == false)
650 return _error->Error("There are problems and -y was used without --force-yes");
651 }
83d89a9f 652
6f86c974
AL
653 if (Essential == true && Saftey == true)
654 {
d150b09d
AL
655 if (_config->FindB("APT::Get::Trivial-Only",false) == true)
656 return _error->Error("Trivial Only specified but this is not a trivial operation.");
657
6f86c974 658 c2out << "You are about to do something potentially harmful" << endl;
36375005 659 c2out << "To continue type in the phrase 'Yes, I understand this may be bad'" << endl;
6f86c974 660 c2out << " ?] " << flush;
36375005 661 if (AnalPrompt("Yes, I understand this may be bad") == false)
6f86c974
AL
662 {
663 c2out << "Abort." << endl;
a6568219 664 exit(1);
6f86c974
AL
665 }
666 }
667 else
d150b09d 668 {
6f86c974 669 // Prompt to continue
38262e68 670 if (Ask == true || Fail == true)
6f86c974 671 {
d150b09d
AL
672 if (_config->FindB("APT::Get::Trivial-Only",false) == true)
673 return _error->Error("Trivial Only specified but this is not a trivial operation.");
674
0c95c765 675 if (_config->FindI("quiet",0) < 2 &&
6f86c974 676 _config->FindB("APT::Get::Assume-Yes",false) == false)
0c95c765 677 {
6f86c974
AL
678 c2out << "Do you want to continue? [Y/n] " << flush;
679
0c95c765
AL
680 if (YnPrompt() == false)
681 {
682 c2out << "Abort." << endl;
683 exit(1);
684 }
685 }
6f86c974
AL
686 }
687 }
688
36375005 689 // Just print out the uris an exit if the --print-uris flag was used
f7a08e33
AL
690 if (_config->FindB("APT::Get::Print-URIs") == true)
691 {
692 pkgAcquire::UriIterator I = Fetcher.UriBegin();
693 for (; I != Fetcher.UriEnd(); I++)
694 cout << '\'' << I->URI << "' " << flNotDir(I->Owner->DestFile) << ' ' <<
695 I->Owner->FileSize << ' ' << I->Owner->MD5Sum() << endl;
696 return true;
697 }
83d89a9f 698
03e39e59 699 // Run it
281daf46 700 while (1)
30e1eab5 701 {
a3eaf954
AL
702 bool Transient = false;
703 if (_config->FindB("APT::Get::No-Download",false) == true)
704 {
705 for (pkgAcquire::Item **I = Fetcher.ItemsBegin(); I < Fetcher.ItemsEnd();)
706 {
707 if ((*I)->Local == true)
708 {
709 I++;
710 continue;
711 }
712
713 // Close the item and check if it was found in cache
714 (*I)->Finished();
715 if ((*I)->Complete == false)
716 Transient = true;
717
718 // Clear it out of the fetch list
719 delete *I;
720 I = Fetcher.ItemsBegin();
721 }
722 }
723
724 if (Fetcher.Run() == pkgAcquire::Failed)
725 return false;
30e1eab5 726
281daf46
AL
727 // Print out errors
728 bool Failed = false;
281daf46 729 for (pkgAcquire::Item **I = Fetcher.ItemsBegin(); I != Fetcher.ItemsEnd(); I++)
f01fe790 730 {
281daf46
AL
731 if ((*I)->Status == pkgAcquire::Item::StatDone &&
732 (*I)->Complete == true)
733 continue;
734
281daf46
AL
735 if ((*I)->Status == pkgAcquire::Item::StatIdle)
736 {
737 Transient = true;
738 // Failed = true;
739 continue;
740 }
a3eaf954 741
281daf46
AL
742 cerr << "Failed to fetch " << (*I)->DescURI() << endl;
743 cerr << " " << (*I)->ErrorText << endl;
f01fe790 744 Failed = true;
f01fe790 745 }
5ec427c2 746
a3eaf954 747 /* If we are in no download mode and missing files and there were
5ec427c2
AL
748 'failures' then the user must specify -m. Furthermore, there
749 is no such thing as a transient error in no-download mode! */
a3eaf954 750 if (Transient == true &&
5ec427c2
AL
751 _config->FindB("APT::Get::No-Download",false) == true)
752 {
753 Transient = false;
754 Failed = true;
755 }
f01fe790 756
281daf46
AL
757 if (_config->FindB("APT::Get::Download-Only",false) == true)
758 {
759 if (Failed == true && _config->FindB("APT::Get::Fix-Missing",false) == false)
760 return _error->Error("Some files failed to download");
761 return true;
762 }
763
8195ae46 764 if (Failed == true && _config->FindB("APT::Get::Fix-Missing",false) == false)
f01fe790 765 {
281daf46 766 return _error->Error("Unable to fetch some archives, maybe try with --fix-missing?");
f01fe790
AL
767 }
768
281daf46
AL
769 if (Transient == true && Failed == true)
770 return _error->Error("--fix-missing and media swapping is not currently supported");
771
772 // Try to deal with missing package files
773 if (Failed == true && PM.FixMissing() == false)
774 {
775 cerr << "Unable to correct missing packages." << endl;
776 return _error->Error("Aborting Install.");
777 }
a3eaf954 778
281daf46
AL
779 Cache.ReleaseLock();
780 pkgPackageManager::OrderResult Res = PM.DoInstall();
781 if (Res == pkgPackageManager::Failed || _error->PendingError() == true)
782 return false;
783 if (Res == pkgPackageManager::Completed)
784 return true;
785
786 // Reload the fetcher object and loop again for media swapping
787 Fetcher.Shutdown();
788 if (PM.GetArchives(&Fetcher,&List,&Recs) == false)
789 return false;
790 }
0a8e3465
AL
791}
792 /*}}}*/
c373c37a
AL
793// TryToInstall - Try to install a single package /*{{{*/
794// ---------------------------------------------------------------------
795/* This used to be inlined in DoInstall, but with the advent of regex package
796 name matching it was split out.. */
797bool TryToInstall(pkgCache::PkgIterator Pkg,pkgDepCache &Cache,
798 pkgProblemResolver &Fix,bool Remove,bool BrokenFix,
799 unsigned int &ExpectedInst,bool AllowFail = true)
800{
801 /* This is a pure virtual package and there is a single available
802 provides */
803 if (Cache[Pkg].CandidateVer == 0 && Pkg->ProvidesList != 0 &&
804 Pkg.ProvidesList()->NextProvides == 0)
805 {
806 pkgCache::PkgIterator Tmp = Pkg.ProvidesList().OwnerPkg();
10bb1f5f 807 c1out << "Note, selecting " << Tmp.Name() << " instead of " << Pkg.Name() << endl;
c373c37a
AL
808 Pkg = Tmp;
809 }
810
811 // Handle the no-upgrade case
812 if (_config->FindB("APT::Get::no-upgrade",false) == true &&
813 Pkg->CurrentVer != 0)
814 {
815 if (AllowFail == true)
816 c1out << "Skipping " << Pkg.Name() << ", it is already installed and no-upgrade is set." << endl;
817 return true;
818 }
819
820 // Check if there is something at all to install
821 pkgDepCache::StateCache &State = Cache[Pkg];
a146c927 822 if (Remove == true && Pkg->CurrentVer == 0)
10bb1f5f
AL
823 {
824 if (AllowFail == false)
825 return false;
a146c927 826 return _error->Error("Package %s is not installed",Pkg.Name());
10bb1f5f 827 }
a146c927
AL
828
829 if (State.CandidateVer == 0 && Remove == false)
c373c37a
AL
830 {
831 if (AllowFail == false)
832 return false;
833
834 if (Pkg->ProvidesList != 0)
835 {
836 c1out << "Package " << Pkg.Name() << " is a virtual package provided by:" << endl;
837
838 pkgCache::PrvIterator I = Pkg.ProvidesList();
839 for (; I.end() == false; I++)
840 {
841 pkgCache::PkgIterator Pkg = I.OwnerPkg();
842
843 if (Cache[Pkg].CandidateVerIter(Cache) == I.OwnerVer())
844 {
845 if (Cache[Pkg].Install() == true && Cache[Pkg].NewInstall() == false)
846 c1out << " " << Pkg.Name() << " " << I.OwnerVer().VerStr() <<
847 " [Installed]"<< endl;
848 else
849 c1out << " " << Pkg.Name() << " " << I.OwnerVer().VerStr() << endl;
850 }
851 }
852 c1out << "You should explicitly select one to install." << endl;
853 }
854 else
855 {
856 c1out << "Package " << Pkg.Name() << " has no available version, but exists in the database." << endl;
857 c1out << "This typically means that the package was mentioned in a dependency and " << endl;
dca1e241
AL
858 c1out << "never uploaded, has been obsoleted or is not available with the contents " << endl;
859 c1out << "of sources.list" << endl;
c373c37a
AL
860
861 string List;
862 pkgCache::DepIterator Dep = Pkg.RevDependsList();
863 for (; Dep.end() == false; Dep++)
864 {
865 if (Dep->Type != pkgCache::Dep::Replaces)
866 continue;
867 List += string(Dep.ParentPkg().Name()) + " ";
868 }
869 ShowList(c1out,"However the following packages replace it:",List);
870 }
871
872 _error->Error("Package %s has no installation candidate",Pkg.Name());
873 return false;
874 }
61d6a8de
AL
875
876 Fix.Clear(Pkg);
70777d4b 877 Fix.Protect(Pkg);
c373c37a
AL
878 if (Remove == true)
879 {
880 Fix.Remove(Pkg);
881 Cache.MarkDelete(Pkg,_config->FindB("APT::Get::Purge",false));
882 return true;
883 }
884
885 // Install it
886 Cache.MarkInstall(Pkg,false);
887 if (State.Install() == false)
888 {
d0c59649
AL
889 if (_config->FindB("APT::Get::ReInstall",false) == true)
890 {
891 if (Pkg->CurrentVer == 0 || Pkg.CurrentVer().Downloadable() == false)
892 c1out << "Sorry, re-installation of " << Pkg.Name() << " is not possible, it cannot be downloaded" << endl;
893 else
894 Cache.SetReInstall(Pkg,true);
895 }
896 else
897 {
898 if (AllowFail == true)
899 c1out << "Sorry, " << Pkg.Name() << " is already the newest version" << endl;
900 }
c373c37a
AL
901 }
902 else
903 ExpectedInst++;
904
905 // Install it with autoinstalling enabled.
906 if (State.InstBroken() == true && BrokenFix == false)
907 Cache.MarkInstall(Pkg,true);
908 return true;
909}
910 /*}}}*/
0a8e3465
AL
911
912// DoUpdate - Update the package lists /*{{{*/
913// ---------------------------------------------------------------------
914/* */
0919e3f9 915bool DoUpdate(CommandLine &)
0a8e3465 916{
0919e3f9
AL
917 // Get the source list
918 pkgSourceList List;
919 if (List.ReadMainList() == false)
920 return false;
921
d38b7b3d 922 // Lock the list directory
36375005 923 FileFd Lock;
d38b7b3d
AL
924 if (_config->FindB("Debug::NoLocking",false) == false)
925 {
36375005 926 Lock.Fd(GetLock(_config->FindDir("Dir::State::Lists") + "lock"));
d38b7b3d
AL
927 if (_error->PendingError() == true)
928 return _error->Error("Unable to lock the list directory");
929 }
930
0919e3f9
AL
931 // Create the download object
932 AcqTextStatus Stat(ScreenWidth,_config->FindI("quiet",0));
933 pkgAcquire Fetcher(&Stat);
934
935 // Populate it with the source selection
936 pkgSourceList::const_iterator I;
937 for (I = List.begin(); I != List.end(); I++)
938 {
939 new pkgAcqIndex(&Fetcher,I);
940 if (_error->PendingError() == true)
941 return false;
942 }
943
944 // Run it
024d1123 945 if (Fetcher.Run() == pkgAcquire::Failed)
0919e3f9
AL
946 return false;
947
9df71a5b
AL
948 bool Failed = false;
949 for (pkgAcquire::Item **I = Fetcher.ItemsBegin(); I != Fetcher.ItemsEnd(); I++)
950 {
951 if ((*I)->Status == pkgAcquire::Item::StatDone)
952 continue;
953
954 (*I)->Finished();
955
eecf9bf7
AL
956 cerr << "Failed to fetch " << (*I)->DescURI() << endl;
957 cerr << " " << (*I)->ErrorText << endl;
9df71a5b
AL
958 Failed = true;
959 }
960
7a7fa5f0 961 // Clean out any old list files
67ff87bf 962 if (_config->FindB("APT::Get::List-Cleanup",true) == true)
9df71a5b
AL
963 {
964 if (Fetcher.Clean(_config->FindDir("Dir::State::lists")) == false ||
965 Fetcher.Clean(_config->FindDir("Dir::State::lists") + "partial/") == false)
966 return false;
967 }
7a7fa5f0 968
0919e3f9
AL
969 // Prepare the cache.
970 CacheFile Cache;
a65cbe33 971 if (Cache.Open() == false)
0919e3f9
AL
972 return false;
973
9df71a5b
AL
974 if (Failed == true)
975 return _error->Error("Some index files failed to download, they have been ignored, or old ones used instead.");
0919e3f9 976 return true;
0a8e3465
AL
977}
978 /*}}}*/
979// DoUpgrade - Upgrade all packages /*{{{*/
980// ---------------------------------------------------------------------
981/* Upgrade all packages without installing new packages or erasing old
982 packages */
983bool DoUpgrade(CommandLine &CmdL)
984{
985 CacheFile Cache;
2d11135a 986 if (Cache.Open() == false || Cache.CheckDeps() == false)
0a8e3465
AL
987 return false;
988
989 // Do the upgrade
0a8e3465
AL
990 if (pkgAllUpgrade(Cache) == false)
991 {
421c8d10 992 ShowBroken(c1out,Cache,false);
0a8e3465
AL
993 return _error->Error("Internal Error, AllUpgrade broke stuff");
994 }
995
996 return InstallPackages(Cache,true);
997}
998 /*}}}*/
999// DoInstall - Install packages from the command line /*{{{*/
1000// ---------------------------------------------------------------------
1001/* Install named packages */
1002bool DoInstall(CommandLine &CmdL)
1003{
1004 CacheFile Cache;
2d11135a 1005 if (Cache.Open() == false || Cache.CheckDeps(CmdL.FileSize() != 1) == false)
0a8e3465
AL
1006 return false;
1007
7c57fe64
AL
1008 // Enter the special broken fixing mode if the user specified arguments
1009 bool BrokenFix = false;
1010 if (Cache->BrokenCount() != 0)
1011 BrokenFix = true;
1012
a6568219
AL
1013 unsigned int ExpectedInst = 0;
1014 unsigned int Packages = 0;
0a8e3465
AL
1015 pkgProblemResolver Fix(Cache);
1016
303a1703
AL
1017 bool DefRemove = false;
1018 if (strcasecmp(CmdL.FileList[0],"remove") == 0)
1019 DefRemove = true;
1020
0a8e3465
AL
1021 for (const char **I = CmdL.FileList + 1; *I != 0; I++)
1022 {
1023 // Duplicate the string
1024 unsigned int Length = strlen(*I);
1025 char S[300];
1026 if (Length >= sizeof(S))
1027 continue;
1028 strcpy(S,*I);
1029
1030 // See if we are removing the package
303a1703 1031 bool Remove = DefRemove;
fc4b5c9f 1032 while (Cache->FindPkg(S).end() == true)
0a8e3465 1033 {
2c3bc8bb
AL
1034 // Handle an optional end tag indicating what to do
1035 if (S[Length - 1] == '-')
1036 {
1037 Remove = true;
1038 S[--Length] = 0;
fc4b5c9f 1039 continue;
2c3bc8bb 1040 }
fc4b5c9f 1041
2c3bc8bb
AL
1042 if (S[Length - 1] == '+')
1043 {
1044 Remove = false;
1045 S[--Length] = 0;
fc4b5c9f 1046 continue;
2c3bc8bb 1047 }
fc4b5c9f 1048 break;
303a1703 1049 }
0a8e3465
AL
1050
1051 // Locate the package
1052 pkgCache::PkgIterator Pkg = Cache->FindPkg(S);
303a1703 1053 Packages++;
0a8e3465 1054 if (Pkg.end() == true)
2c3bc8bb 1055 {
c373c37a
AL
1056 // Check if the name is a regex
1057 const char *I;
1058 for (I = S; *I != 0; I++)
1059 if (*I == '.' || *I == '?' || *I == '*')
1060 break;
1061 if (*I == 0)
1062 return _error->Error("Couldn't find package %s",S);
303a1703 1063
c373c37a
AL
1064 // Regexs must always be confirmed
1065 ExpectedInst += 1000;
1066
1067 // Compile the regex pattern
1068 regex_t Pattern;
1069 if (regcomp(&Pattern,S,REG_EXTENDED | REG_ICASE |
1070 REG_NOSUB) != 0)
1071 return _error->Error("Regex compilation error");
1072
1073 // Run over the matches
1074 bool Hit = false;
1075 for (Pkg = Cache->PkgBegin(); Pkg.end() == false; Pkg++)
303a1703 1076 {
c373c37a
AL
1077 if (regexec(&Pattern,Pkg.Name(),0,0,0) != 0)
1078 continue;
07801a6d 1079
c373c37a
AL
1080 Hit |= TryToInstall(Pkg,Cache,Fix,Remove,BrokenFix,
1081 ExpectedInst,false);
303a1703 1082 }
c373c37a 1083 regfree(&Pattern);
303a1703 1084
c373c37a
AL
1085 if (Hit == false)
1086 return _error->Error("Couldn't find package %s",S);
0a8e3465 1087 }
0a8e3465 1088 else
c373c37a
AL
1089 {
1090 if (TryToInstall(Pkg,Cache,Fix,Remove,BrokenFix,ExpectedInst) == false)
1091 return false;
1092 }
0a8e3465
AL
1093 }
1094
7c57fe64
AL
1095 /* If we are in the Broken fixing mode we do not attempt to fix the
1096 problems. This is if the user invoked install without -f and gave
1097 packages */
1098 if (BrokenFix == true && Cache->BrokenCount() != 0)
1099 {
b5dc9785 1100 c1out << "You might want to run `apt-get -f install' to correct these:" << endl;
421c8d10 1101 ShowBroken(c1out,Cache,false);
7c57fe64 1102
b5dc9785 1103 return _error->Error("Unmet dependencies. Try 'apt-get -f install' with no packages (or specify a solution).");
7c57fe64
AL
1104 }
1105
0a8e3465 1106 // Call the scored problem resolver
303a1703 1107 Fix.InstallProtect();
0a8e3465
AL
1108 if (Fix.Resolve(true) == false)
1109 _error->Discard();
1110
1111 // Now we check the state of the packages,
1112 if (Cache->BrokenCount() != 0)
1113 {
303a1703
AL
1114 c1out << "Some packages could not be installed. This may mean that you have" << endl;
1115 c1out << "requested an impossible situation or if you are using the unstable" << endl;
1116 c1out << "distribution that some required packages have not yet been created" << endl;
1117 c1out << "or been moved out of Incoming." << endl;
1118 if (Packages == 1)
1119 {
1120 c1out << endl;
1121 c1out << "Since you only requested a single operation it is extremely likely that" << endl;
1122 c1out << "the package is simply not installable and a bug report against" << endl;
1123 c1out << "that package should be filed." << endl;
1124 }
1125
1126 c1out << "The following information may help to resolve the situation:" << endl;
1127 c1out << endl;
421c8d10 1128 ShowBroken(c1out,Cache,false);
0a8e3465
AL
1129 return _error->Error("Sorry, broken packages");
1130 }
1131
1132 /* Print out a list of packages that are going to be installed extra
1133 to what the user asked */
1134 if (Cache->InstCount() != ExpectedInst)
1135 {
1136 string List;
1089ca89 1137 for (unsigned J = 0; J < Cache->Head().PackageCount; J++)
0a8e3465 1138 {
1089ca89 1139 pkgCache::PkgIterator I(Cache,Cache.List[J]);
0a8e3465
AL
1140 if ((*Cache)[I].Install() == false)
1141 continue;
1142
1143 const char **J;
1144 for (J = CmdL.FileList + 1; *J != 0; J++)
1145 if (strcmp(*J,I.Name()) == 0)
1146 break;
1147
1148 if (*J == 0)
1149 List += string(I.Name()) + " ";
1150 }
1151
1152 ShowList(c1out,"The following extra packages will be installed:",List);
1153 }
1154
03e39e59 1155 // See if we need to prompt
2c3bc8bb 1156 if (Cache->InstCount() == ExpectedInst && Cache->DelCount() == 0)
2c3bc8bb 1157 return InstallPackages(Cache,false,false);
2c3bc8bb 1158
03e39e59 1159 return InstallPackages(Cache,false);
0a8e3465
AL
1160}
1161 /*}}}*/
1162// DoDistUpgrade - Automatic smart upgrader /*{{{*/
1163// ---------------------------------------------------------------------
1164/* Intelligent upgrader that will install and remove packages at will */
1165bool DoDistUpgrade(CommandLine &CmdL)
1166{
1167 CacheFile Cache;
2d11135a 1168 if (Cache.Open() == false || Cache.CheckDeps() == false)
0a8e3465
AL
1169 return false;
1170
1171 c0out << "Calculating Upgrade... " << flush;
1172 if (pkgDistUpgrade(*Cache) == false)
1173 {
1174 c0out << "Failed" << endl;
421c8d10 1175 ShowBroken(c1out,Cache,false);
0a8e3465
AL
1176 return false;
1177 }
1178
1179 c0out << "Done" << endl;
1180
1181 return InstallPackages(Cache,true);
1182}
1183 /*}}}*/
1184// DoDSelectUpgrade - Do an upgrade by following dselects selections /*{{{*/
1185// ---------------------------------------------------------------------
1186/* Follows dselect's selections */
1187bool DoDSelectUpgrade(CommandLine &CmdL)
1188{
1189 CacheFile Cache;
2d11135a 1190 if (Cache.Open() == false || Cache.CheckDeps() == false)
0a8e3465
AL
1191 return false;
1192
1193 // Install everything with the install flag set
1194 pkgCache::PkgIterator I = Cache->PkgBegin();
1195 for (;I.end() != true; I++)
1196 {
1197 /* Install the package only if it is a new install, the autoupgrader
1198 will deal with the rest */
1199 if (I->SelectedState == pkgCache::State::Install)
1200 Cache->MarkInstall(I,false);
1201 }
1202
1203 /* Now install their deps too, if we do this above then order of
1204 the status file is significant for | groups */
1205 for (I = Cache->PkgBegin();I.end() != true; I++)
1206 {
1207 /* Install the package only if it is a new install, the autoupgrader
1208 will deal with the rest */
1209 if (I->SelectedState == pkgCache::State::Install)
2f45c76a 1210 Cache->MarkInstall(I,true);
0a8e3465
AL
1211 }
1212
1213 // Apply erasures now, they override everything else.
1214 for (I = Cache->PkgBegin();I.end() != true; I++)
1215 {
1216 // Remove packages
1217 if (I->SelectedState == pkgCache::State::DeInstall ||
1218 I->SelectedState == pkgCache::State::Purge)
d556d1a1 1219 Cache->MarkDelete(I,I->SelectedState == pkgCache::State::Purge);
0a8e3465
AL
1220 }
1221
2f45c76a
AL
1222 /* Resolve any problems that dselect created, allupgrade cannot handle
1223 such things. We do so quite agressively too.. */
1224 if (Cache->BrokenCount() != 0)
1225 {
1226 pkgProblemResolver Fix(Cache);
1227
1228 // Hold back held packages.
1229 if (_config->FindB("APT::Ingore-Hold",false) == false)
1230 {
1231 for (pkgCache::PkgIterator I = Cache->PkgBegin(); I.end() == false; I++)
1232 {
1233 if (I->SelectedState == pkgCache::State::Hold)
1234 {
1235 Fix.Protect(I);
1236 Cache->MarkKeep(I);
1237 }
1238 }
1239 }
1240
1241 if (Fix.Resolve() == false)
1242 {
421c8d10 1243 ShowBroken(c1out,Cache,false);
2f45c76a
AL
1244 return _error->Error("Internal Error, problem resolver broke stuff");
1245 }
1246 }
1247
1248 // Now upgrade everything
0a8e3465
AL
1249 if (pkgAllUpgrade(Cache) == false)
1250 {
421c8d10 1251 ShowBroken(c1out,Cache,false);
2f45c76a 1252 return _error->Error("Internal Error, problem resolver broke stuff");
0a8e3465
AL
1253 }
1254
1255 return InstallPackages(Cache,false);
1256}
1257 /*}}}*/
1258// DoClean - Remove download archives /*{{{*/
1259// ---------------------------------------------------------------------
1260/* */
1261bool DoClean(CommandLine &CmdL)
1262{
8b067c22
AL
1263 if (_config->FindB("APT::Get::Simulate") == true)
1264 {
1265 cout << "Del " << _config->FindDir("Dir::Cache::archives") << "* " <<
1266 _config->FindDir("Dir::Cache::archives") << "partial/*" << endl;
1267 return true;
1268 }
1269
1b6d659c
AL
1270 // Lock the archive directory
1271 FileFd Lock;
1272 if (_config->FindB("Debug::NoLocking",false) == false)
1273 {
1274 Lock.Fd(GetLock(_config->FindDir("Dir::Cache::Archives") + "lock"));
1275 if (_error->PendingError() == true)
1276 return _error->Error("Unable to lock the download directory");
1277 }
1278
7a1b1f8b
AL
1279 pkgAcquire Fetcher;
1280 Fetcher.Clean(_config->FindDir("Dir::Cache::archives"));
1281 Fetcher.Clean(_config->FindDir("Dir::Cache::archives") + "partial/");
0a8e3465
AL
1282 return true;
1283}
1284 /*}}}*/
1bc849af
AL
1285// DoAutoClean - Smartly remove downloaded archives /*{{{*/
1286// ---------------------------------------------------------------------
1287/* This is similar to clean but it only purges things that cannot be
1288 downloaded, that is old versions of cached packages. */
65a1e968
AL
1289class LogCleaner : public pkgArchiveCleaner
1290{
1291 protected:
1292 virtual void Erase(const char *File,string Pkg,string Ver,struct stat &St)
1293 {
4cc8bab0 1294 c1out << "Del " << Pkg << " " << Ver << " [" << SizeToStr(St.st_size) << "B]" << endl;
c1e78ee5
AL
1295
1296 if (_config->FindB("APT::Get::Simulate") == false)
1297 unlink(File);
65a1e968
AL
1298 };
1299};
1300
1bc849af
AL
1301bool DoAutoClean(CommandLine &CmdL)
1302{
1b6d659c
AL
1303 // Lock the archive directory
1304 FileFd Lock;
1305 if (_config->FindB("Debug::NoLocking",false) == false)
1306 {
1307 Lock.Fd(GetLock(_config->FindDir("Dir::Cache::Archives") + "lock"));
1308 if (_error->PendingError() == true)
1309 return _error->Error("Unable to lock the download directory");
1310 }
1311
1bc849af 1312 CacheFile Cache;
2d11135a 1313 if (Cache.Open() == false)
1bc849af
AL
1314 return false;
1315
65a1e968 1316 LogCleaner Cleaner;
1bc849af
AL
1317
1318 return Cleaner.Go(_config->FindDir("Dir::Cache::archives"),*Cache) &&
1319 Cleaner.Go(_config->FindDir("Dir::Cache::archives") + "partial/",*Cache);
1320}
1321 /*}}}*/
0a8e3465
AL
1322// DoCheck - Perform the check operation /*{{{*/
1323// ---------------------------------------------------------------------
1324/* Opening automatically checks the system, this command is mostly used
1325 for debugging */
1326bool DoCheck(CommandLine &CmdL)
1327{
1328 CacheFile Cache;
1329 Cache.Open();
2d11135a 1330 Cache.CheckDeps();
0a8e3465
AL
1331
1332 return true;
1333}
1334 /*}}}*/
36375005
AL
1335// DoSource - Fetch a source archive /*{{{*/
1336// ---------------------------------------------------------------------
2d11135a 1337/* Fetch souce packages */
fb0ee66e
AL
1338struct DscFile
1339{
1340 string Package;
1341 string Version;
1342 string Dsc;
1343};
1344
36375005
AL
1345bool DoSource(CommandLine &CmdL)
1346{
1347 CacheFile Cache;
2d11135a 1348 if (Cache.Open(false) == false)
36375005
AL
1349 return false;
1350
2d11135a
AL
1351 if (CmdL.FileSize() <= 1)
1352 return _error->Error("Must specify at least one package to fetch source for");
1353
36375005
AL
1354 // Read the source list
1355 pkgSourceList List;
1356 if (List.ReadMainList() == false)
1357 return _error->Error("The list of sources could not be read.");
1358
1359 // Create the text record parsers
1360 pkgRecords Recs(Cache);
1361 pkgSrcRecords SrcRecs(List);
1362 if (_error->PendingError() == true)
1363 return false;
1364
1365 // Create the download object
1366 AcqTextStatus Stat(ScreenWidth,_config->FindI("quiet",0));
1367 pkgAcquire Fetcher(&Stat);
fb0ee66e
AL
1368
1369 DscFile *Dsc = new DscFile[CmdL.FileSize()];
36375005
AL
1370
1371 // Load the requestd sources into the fetcher
fb0ee66e
AL
1372 unsigned J = 0;
1373 for (const char **I = CmdL.FileList + 1; *I != 0; I++, J++)
36375005
AL
1374 {
1375 string Src;
0a8e3465 1376
36375005
AL
1377 /* Lookup the version of the package we would install if we were to
1378 install a version and determine the source package name, then look
1379 in the archive for a source package of the same name. In theory
1380 we could stash the version string as well and match that too but
1381 today there aren't multi source versions in the archive. */
1382 pkgCache::PkgIterator Pkg = Cache->FindPkg(*I);
1383 if (Pkg.end() == false)
1384 {
1385 pkgCache::VerIterator Ver = Cache->GetCandidateVer(Pkg);
1386 if (Ver.end() == false)
1387 {
1388 pkgRecords::Parser &Parse = Recs.Lookup(Ver.FileList());
1389 Src = Parse.SourcePkg();
1390 }
1391 }
1392
1393 // No source package name..
1394 if (Src.empty() == true)
1395 Src = *I;
1396
1397 // The best hit
1398 pkgSrcRecords::Parser *Last = 0;
1399 unsigned long Offset = 0;
1400 string Version;
73c2c61b 1401 bool IsMatch = false;
36375005
AL
1402
1403 // Iterate over all of the hits
1404 pkgSrcRecords::Parser *Parse;
1405 SrcRecs.Restart();
1406 while ((Parse = SrcRecs.Find(Src.c_str(),false)) != 0)
1407 {
1408 string Ver = Parse->Version();
73c2c61b
AL
1409
1410 // Skip name mismatches
1411 if (IsMatch == true && Parse->Package() != Src)
1412 continue;
1413
1414 // Newer version or an exact match
1415 if (Last == 0 || pkgVersionCompare(Version,Ver) < 0 ||
1416 (Parse->Package() == Src && IsMatch == false))
36375005 1417 {
73c2c61b 1418 IsMatch = Parse->Package() == Src;
36375005
AL
1419 Last = Parse;
1420 Offset = Parse->Offset();
1421 Version = Ver;
1422 }
1423 }
1424
1425 if (Last == 0)
1426 return _error->Error("Unable to find a source package for %s",Src.c_str());
1427
1428 // Back track
1429 vector<pkgSrcRecords::File> Lst;
1430 if (Last->Jump(Offset) == false || Last->Files(Lst) == false)
1431 return false;
1432
1433 // Load them into the fetcher
1434 for (vector<pkgSrcRecords::File>::const_iterator I = Lst.begin();
1435 I != Lst.end(); I++)
1436 {
1437 // Try to guess what sort of file it is we are getting.
1438 string Comp;
1439 if (I->Path.find(".dsc") != string::npos)
fb0ee66e 1440 {
36375005 1441 Comp = "dsc";
fb0ee66e
AL
1442 Dsc[J].Package = Last->Package();
1443 Dsc[J].Version = Last->Version();
1444 Dsc[J].Dsc = flNotDir(I->Path);
1445 }
1446
36375005
AL
1447 if (I->Path.find(".tar.gz") != string::npos)
1448 Comp = "tar";
1449 if (I->Path.find(".diff.gz") != string::npos)
1450 Comp = "diff";
1451
17c0e8e1
AL
1452 // Diff only mode only fetches .diff files
1453 if (_config->FindB("APT::Get::Diff-Only",false) == true &&
1454 Comp != "diff")
1455 continue;
1456
1457 // Tar only mode only fetches .tar files
1458 if (_config->FindB("APT::Get::Tar-Only",false) == true &&
1459 Comp != "tar")
1460 continue;
1461
36375005
AL
1462 new pkgAcqFile(&Fetcher,Last->Source()->ArchiveURI(I->Path),
1463 I->MD5Hash,I->Size,Last->Source()->SourceInfo(Src,
1464 Last->Version(),Comp),Src);
1465 }
1466 }
1467
1468 // Display statistics
1469 unsigned long FetchBytes = Fetcher.FetchNeeded();
1470 unsigned long FetchPBytes = Fetcher.PartialPresent();
1471 unsigned long DebBytes = Fetcher.TotalNeeded();
1472
1473 // Check for enough free space
f332b62b 1474 struct statvfs Buf;
36375005 1475 string OutputDir = ".";
f332b62b
AL
1476 if (statvfs(OutputDir.c_str(),&Buf) != 0)
1477 return _error->Errno("statvfs","Couldn't determine free space in %s",
36375005
AL
1478 OutputDir.c_str());
1479 if (unsigned(Buf.f_bfree) < (FetchBytes - FetchPBytes)/Buf.f_bsize)
1480 return _error->Error("Sorry, you don't have enough free space in %s",
1481 OutputDir.c_str());
1482
1483 // Number of bytes
1484 c1out << "Need to get ";
1485 if (DebBytes != FetchBytes)
314037ba 1486 c1out << SizeToStr(FetchBytes) << "B/" << SizeToStr(DebBytes) << 'B';
36375005 1487 else
314037ba 1488 c1out << SizeToStr(DebBytes) << 'B';
36375005
AL
1489 c1out << " of source archives." << endl;
1490
2c0c53b3
AL
1491 if (_config->FindB("APT::Get::Simulate",false) == true)
1492 {
1493 for (unsigned I = 0; I != J; I++)
1494 cout << "Fetch Source " << Dsc[I].Package << endl;
1495 return true;
1496 }
1497
36375005
AL
1498 // Just print out the uris an exit if the --print-uris flag was used
1499 if (_config->FindB("APT::Get::Print-URIs") == true)
1500 {
1501 pkgAcquire::UriIterator I = Fetcher.UriBegin();
1502 for (; I != Fetcher.UriEnd(); I++)
1503 cout << '\'' << I->URI << "' " << flNotDir(I->Owner->DestFile) << ' ' <<
1504 I->Owner->FileSize << ' ' << I->Owner->MD5Sum() << endl;
1505 return true;
1506 }
1507
1508 // Run it
024d1123 1509 if (Fetcher.Run() == pkgAcquire::Failed)
36375005
AL
1510 return false;
1511
1512 // Print error messages
fb0ee66e 1513 bool Failed = false;
36375005
AL
1514 for (pkgAcquire::Item **I = Fetcher.ItemsBegin(); I != Fetcher.ItemsEnd(); I++)
1515 {
1516 if ((*I)->Status == pkgAcquire::Item::StatDone &&
1517 (*I)->Complete == true)
1518 continue;
1519
1520 cerr << "Failed to fetch " << (*I)->DescURI() << endl;
1521 cerr << " " << (*I)->ErrorText << endl;
fb0ee66e 1522 Failed = true;
36375005 1523 }
fb0ee66e
AL
1524 if (Failed == true)
1525 return _error->Error("Failed to fetch some archives.");
1526
1527 if (_config->FindB("APT::Get::Download-only",false) == true)
1528 return true;
36375005 1529
fb0ee66e 1530 // Unpack the sources
54676e1a
AL
1531 pid_t Process = ExecFork();
1532
1533 if (Process == 0)
fb0ee66e 1534 {
54676e1a 1535 for (unsigned I = 0; I != J; I++)
fb0ee66e 1536 {
54676e1a 1537 string Dir = Dsc[I].Package + '-' + pkgBaseVersion(Dsc[I].Version.c_str());
fb0ee66e 1538
17c0e8e1
AL
1539 // Diff only mode only fetches .diff files
1540 if (_config->FindB("APT::Get::Diff-Only",false) == true ||
a3eaf954
AL
1541 _config->FindB("APT::Get::Tar-Only",false) == true ||
1542 Dsc[I].Dsc.empty() == true)
17c0e8e1 1543 continue;
a3eaf954 1544
54676e1a
AL
1545 // See if the package is already unpacked
1546 struct stat Stat;
1547 if (stat(Dir.c_str(),&Stat) == 0 &&
1548 S_ISDIR(Stat.st_mode) != 0)
1549 {
1550 c0out << "Skipping unpack of already unpacked source in " << Dir << endl;
1551 }
1552 else
1553 {
1554 // Call dpkg-source
1555 char S[500];
1556 snprintf(S,sizeof(S),"%s -x %s",
1557 _config->Find("Dir::Bin::dpkg-source","dpkg-source").c_str(),
1558 Dsc[I].Dsc.c_str());
1559 if (system(S) != 0)
1560 {
1561 cerr << "Unpack command '" << S << "' failed." << endl;
1562 _exit(1);
1563 }
1564 }
1565
1566 // Try to compile it with dpkg-buildpackage
1567 if (_config->FindB("APT::Get::Compile",false) == true)
1568 {
1569 // Call dpkg-buildpackage
1570 char S[500];
1571 snprintf(S,sizeof(S),"cd %s && %s %s",
1572 Dir.c_str(),
1573 _config->Find("Dir::Bin::dpkg-buildpackage","dpkg-buildpackage").c_str(),
1574 _config->Find("DPkg::Build-Options","-b -uc").c_str());
1575
1576 if (system(S) != 0)
1577 {
1578 cerr << "Build command '" << S << "' failed." << endl;
1579 _exit(1);
1580 }
1581 }
1582 }
1583
1584 _exit(0);
1585 }
1586
1587 // Wait for the subprocess
1588 int Status = 0;
1589 while (waitpid(Process,&Status,0) != Process)
1590 {
1591 if (errno == EINTR)
1592 continue;
1593 return _error->Errno("waitpid","Couldn't wait for subprocess");
1594 }
1595
1596 if (WIFEXITED(Status) == 0 || WEXITSTATUS(Status) != 0)
1597 return _error->Error("Child process failed");
1598
36375005
AL
1599 return true;
1600}
1601 /*}}}*/
1602
0a8e3465
AL
1603// ShowHelp - Show a help screen /*{{{*/
1604// ---------------------------------------------------------------------
1605/* */
212ad54a 1606bool ShowHelp(CommandLine &CmdL)
0a8e3465
AL
1607{
1608 cout << PACKAGE << ' ' << VERSION << " for " << ARCHITECTURE <<
1609 " compiled on " << __DATE__ << " " << __TIME__ << endl;
04aa15a8
AL
1610 if (_config->FindB("version") == true)
1611 return 100;
1612
0a8e3465 1613 cout << "Usage: apt-get [options] command" << endl;
d82d6873
AL
1614 cout << " apt-get [options] install|remove pkg1 [pkg2 ...]" << endl;
1615 cout << " apt-get [options] source pkg1 [pkg2 ...]" << endl;
0a8e3465
AL
1616 cout << endl;
1617 cout << "apt-get is a simple command line interface for downloading and" << endl;
1618 cout << "installing packages. The most frequently used commands are update" << endl;
1619 cout << "and install." << endl;
1620 cout << endl;
1621 cout << "Commands:" << endl;
1622 cout << " update - Retrieve new lists of packages" << endl;
1623 cout << " upgrade - Perform an upgrade" << endl;
1624 cout << " install - Install new packages (pkg is libc6 not libc6.deb)" << endl;
303a1703 1625 cout << " remove - Remove packages" << endl;
4994560c 1626 cout << " source - Download source archives" << endl;
0a8e3465
AL
1627 cout << " dist-upgrade - Distribution upgrade, see apt-get(8)" << endl;
1628 cout << " dselect-upgrade - Follow dselect selections" << endl;
1629 cout << " clean - Erase downloaded archive files" << endl;
1bc849af 1630 cout << " autoclean - Erase old downloaded archive files" << endl;
0a8e3465
AL
1631 cout << " check - Verify that there are no broken dependencies" << endl;
1632 cout << endl;
1633 cout << "Options:" << endl;
c217f42a
AL
1634 cout << " -h This help text." << endl;
1635 cout << " -q Loggable output - no progress indicator" << endl;
0a8e3465
AL
1636 cout << " -qq No output except for errors" << endl;
1637 cout << " -d Download only - do NOT install or unpack archives" << endl;
1638 cout << " -s No-act. Perform ordering simulation" << endl;
1639 cout << " -y Assume Yes to all queries and do not prompt" << endl;
1640 cout << " -f Attempt to continue if the integrity check fails" << endl;
1641 cout << " -m Attempt to continue if archives are unlocatable" << endl;
1642 cout << " -u Show a list of upgraded packages as well" << endl;
b5dc9785 1643 cout << " -b Build the source package after fetching it" << endl;
0a8e3465 1644 cout << " -c=? Read this configuration file" << endl;
7974b907 1645 cout << " -o=? Set an arbitary configuration option, eg -o dir::cache=/tmp" << endl;
21ae3cae 1646 cout << "See the apt-get(8), sources.list(5) and apt.conf(5) manual" << endl;
fc4b5c9f 1647 cout << "pages for more information and options." << endl;
0a8e3465
AL
1648 return 100;
1649}
1650 /*}}}*/
1651// GetInitialize - Initialize things for apt-get /*{{{*/
1652// ---------------------------------------------------------------------
1653/* */
1654void GetInitialize()
1655{
1656 _config->Set("quiet",0);
1657 _config->Set("help",false);
1658 _config->Set("APT::Get::Download-Only",false);
1659 _config->Set("APT::Get::Simulate",false);
1660 _config->Set("APT::Get::Assume-Yes",false);
1661 _config->Set("APT::Get::Fix-Broken",false);
83d89a9f 1662 _config->Set("APT::Get::Force-Yes",false);
9df71a5b 1663 _config->Set("APT::Get::APT::Get::No-List-Cleanup",true);
0a8e3465
AL
1664}
1665 /*}}}*/
d7827aca
AL
1666// SigWinch - Window size change signal handler /*{{{*/
1667// ---------------------------------------------------------------------
1668/* */
1669void SigWinch(int)
1670{
1671 // Riped from GNU ls
1672#ifdef TIOCGWINSZ
1673 struct winsize ws;
1674
1675 if (ioctl(1, TIOCGWINSZ, &ws) != -1 && ws.ws_col >= 5)
1676 ScreenWidth = ws.ws_col - 1;
1677#endif
1678}
1679 /*}}}*/
0a8e3465
AL
1680
1681int main(int argc,const char *argv[])
1682{
1683 CommandLine::Args Args[] = {
1684 {'h',"help","help",0},
04aa15a8 1685 {'v',"version","version",0},
0a8e3465
AL
1686 {'q',"quiet","quiet",CommandLine::IntLevel},
1687 {'q',"silent","quiet",CommandLine::IntLevel},
1688 {'d',"download-only","APT::Get::Download-Only",0},
fb0ee66e
AL
1689 {'b',"compile","APT::Get::Compile",0},
1690 {'b',"build","APT::Get::Compile",0},
d150b09d
AL
1691 {'s',"simulate","APT::Get::Simulate",0},
1692 {'s',"just-print","APT::Get::Simulate",0},
1693 {'s',"recon","APT::Get::Simulate",0},
1694 {'s',"no-act","APT::Get::Simulate",0},
1695 {'y',"yes","APT::Get::Assume-Yes",0},
0a8e3465
AL
1696 {'y',"assume-yes","APT::Get::Assume-Yes",0},
1697 {'f',"fix-broken","APT::Get::Fix-Broken",0},
1698 {'u',"show-upgraded","APT::Get::Show-Upgraded",0},
30e1eab5 1699 {'m',"ignore-missing","APT::Get::Fix-Missing",0},
ab559b35 1700 {0,"no-download","APT::Get::No-Download",0},
30e1eab5 1701 {0,"fix-missing","APT::Get::Fix-Missing",0},
c88edf1d 1702 {0,"ignore-hold","APT::Ingore-Hold",0},
83d89a9f
AL
1703 {0,"no-upgrade","APT::Get::no-upgrade",0},
1704 {0,"force-yes","APT::Get::force-yes",0},
f7a08e33 1705 {0,"print-uris","APT::Get::Print-URIs",0},
5fafc0ef
AL
1706 {0,"diff-only","APT::Get::Diff-Only",0},
1707 {0,"tar-only","APT::Get::tar-Only",0},
fc4b5c9f 1708 {0,"purge","APT::Get::Purge",0},
9df71a5b 1709 {0,"list-cleanup","APT::Get::List-Cleanup",0},
d0c59649 1710 {0,"reinstall","APT::Get::ReInstall",0},
d150b09d
AL
1711 {0,"trivial-only","APT::Get::Trivial-Only",0},
1712 {0,"no-remove","APT::Get::No-Remove",0},
0a8e3465
AL
1713 {'c',"config-file",0,CommandLine::ConfigFile},
1714 {'o',"option",0,CommandLine::ArbItem},
1715 {0,0,0,0}};
83d89a9f
AL
1716 CommandLine::Dispatch Cmds[] = {{"update",&DoUpdate},
1717 {"upgrade",&DoUpgrade},
1718 {"install",&DoInstall},
1719 {"remove",&DoInstall},
1720 {"dist-upgrade",&DoDistUpgrade},
1721 {"dselect-upgrade",&DoDSelectUpgrade},
1722 {"clean",&DoClean},
1bc849af 1723 {"autoclean",&DoAutoClean},
83d89a9f 1724 {"check",&DoCheck},
36375005 1725 {"source",&DoSource},
3d615484 1726 {"help",&ShowHelp},
83d89a9f 1727 {0,0}};
0a8e3465
AL
1728
1729 // Parse the command line and initialize the package library
1730 CommandLine CmdL(Args,_config);
1731 if (pkgInitialize(*_config) == false ||
1732 CmdL.Parse(argc,argv) == false)
1733 {
1734 _error->DumpErrors();
1735 return 100;
1736 }
1737
1738 // See if the help should be shown
1739 if (_config->FindB("help") == true ||
04aa15a8 1740 _config->FindB("version") == true ||
0a8e3465 1741 CmdL.FileSize() == 0)
3d615484 1742 return ShowHelp(CmdL);
67ff87bf 1743
a9a5908d
AL
1744 // Deal with stdout not being a tty
1745 if (ttyname(STDOUT_FILENO) == 0 && _config->FindI("quiet",0) < 1)
1746 _config->Set("quiet","1");
01b64152 1747
0a8e3465
AL
1748 // Setup the output streams
1749 c0out.rdbuf(cout.rdbuf());
1750 c1out.rdbuf(cout.rdbuf());
1751 c2out.rdbuf(cout.rdbuf());
1752 if (_config->FindI("quiet",0) > 0)
1753 c0out.rdbuf(devnull.rdbuf());
1754 if (_config->FindI("quiet",0) > 1)
1755 c1out.rdbuf(devnull.rdbuf());
d7827aca
AL
1756
1757 // Setup the signals
1758 signal(SIGPIPE,SIG_IGN);
1759 signal(SIGWINCH,SigWinch);
1760 SigWinch(0);
0a8e3465
AL
1761
1762 // Match the operation
83d89a9f 1763 CmdL.DispatchArg(Cmds);
0a8e3465
AL
1764
1765 // Print any errors or warnings found during parsing
1766 if (_error->empty() == false)
1767 {
1768 bool Errors = _error->PendingError();
1769 _error->DumpErrors();
0a8e3465
AL
1770 return Errors == true?100:0;
1771 }
1772
1773 return 0;
1774}