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