]> git.saurik.com Git - apt.git/blob - cmdline/apt-get.cc
f0405e75c62e5b1acba78d6b5a91fa49b8738e0b
[apt.git] / cmdline / apt-get.cc
1 // -*- mode: cpp; mode: fold -*-
2 // Description /*{{{*/
3 // $Id: apt-get.cc,v 1.156 2004/08/28 01:05:16 mdz Exp $
4 /* ######################################################################
5
6 apt-get - Cover for dpkg
7
8 This is an allout cover for dpkg implementing a safer front end. It is
9 based largely on libapt-pkg.
10
11 The syntax is different,
12 apt-get [opt] command [things]
13 Where command is:
14 update - Resyncronize the package files from their sources
15 upgrade - Smart-Download the newest versions of all packages
16 dselect-upgrade - Follows dselect's changes to the Status: field
17 and installes new and removes old packages
18 dist-upgrade - Powerfull upgrader designed to handle the issues with
19 a new distribution.
20 install - Download and install a given package (by name, not by .deb)
21 check - Update the package cache and check for broken packages
22 clean - Erase the .debs downloaded to /var/cache/apt/archives and
23 the partial dir too
24
25 ##################################################################### */
26 /*}}}*/
27 // Include Files /*{{{*/
28 #include <config.h>
29
30 #include <apt-pkg/aptconfiguration.h>
31 #include <apt-pkg/error.h>
32 #include <apt-pkg/cmndline.h>
33 #include <apt-pkg/init.h>
34 #include <apt-pkg/depcache.h>
35 #include <apt-pkg/sourcelist.h>
36 #include <apt-pkg/algorithms.h>
37 #include <apt-pkg/acquire-item.h>
38 #include <apt-pkg/strutl.h>
39 #include <apt-pkg/fileutl.h>
40 #include <apt-pkg/clean.h>
41 #include <apt-pkg/srcrecords.h>
42 #include <apt-pkg/version.h>
43 #include <apt-pkg/cachefile.h>
44 #include <apt-pkg/cacheset.h>
45 #include <apt-pkg/sptr.h>
46 #include <apt-pkg/md5.h>
47 #include <apt-pkg/versionmatch.h>
48 #include <apt-pkg/progress.h>
49 #include <apt-pkg/pkgsystem.h>
50 #include <apt-pkg/pkgrecords.h>
51 #include <apt-pkg/indexfile.h>
52 #include <apt-pkg/upgrade.h>
53 #include <apt-pkg/metaindex.h>
54 #include <apt-pkg/indexrecords.h>
55
56 #include <apt-private/private-download.h>
57 #include <apt-private/private-install.h>
58 #include <apt-private/private-upgrade.h>
59 #include <apt-private/private-output.h>
60 #include <apt-private/private-cacheset.h>
61 #include <apt-private/private-update.h>
62 #include <apt-private/private-cmndline.h>
63 #include <apt-private/private-moo.h>
64 #include <apt-private/private-utils.h>
65
66 #include <apt-pkg/debmetaindex.h>
67
68 #include <apt-private/acqprogress.h>
69
70 #include <set>
71 #include <fstream>
72 #include <sstream>
73
74 #include <locale.h>
75 #include <langinfo.h>
76 #include <termios.h>
77 #include <sys/ioctl.h>
78 #include <sys/stat.h>
79 #include <sys/statfs.h>
80 #include <sys/statvfs.h>
81 #include <signal.h>
82 #include <unistd.h>
83 #include <stdio.h>
84 #include <errno.h>
85 #include <regex.h>
86 #include <sys/wait.h>
87
88 #include <apt-private/private-output.h>
89 #include <apt-private/private-main.h>
90
91 #include <apti18n.h>
92 /*}}}*/
93
94 using namespace std;
95
96 // TryToInstallBuildDep - Try to install a single package /*{{{*/
97 // ---------------------------------------------------------------------
98 /* This used to be inlined in DoInstall, but with the advent of regex package
99 name matching it was split out.. */
100 bool TryToInstallBuildDep(pkgCache::PkgIterator Pkg,pkgCacheFile &Cache,
101 pkgProblemResolver &Fix,bool Remove,bool BrokenFix,
102 bool AllowFail = true)
103 {
104 if (Cache[Pkg].CandidateVer == 0 && Pkg->ProvidesList != 0)
105 {
106 CacheSetHelperAPTGet helper(c1out);
107 helper.showErrors(false);
108 pkgCache::VerIterator Ver = helper.canNotFindNewestVer(Cache, Pkg);
109 if (Ver.end() == false)
110 Pkg = Ver.ParentPkg();
111 else if (helper.showVirtualPackageErrors(Cache) == false)
112 return AllowFail;
113 }
114
115 if (_config->FindB("Debug::BuildDeps",false) == true)
116 {
117 if (Remove == true)
118 cout << " Trying to remove " << Pkg << endl;
119 else
120 cout << " Trying to install " << Pkg << endl;
121 }
122
123 if (Remove == true)
124 {
125 TryToRemove RemoveAction(Cache, &Fix);
126 RemoveAction(Pkg.VersionList());
127 } else if (Cache[Pkg].CandidateVer != 0) {
128 TryToInstall InstallAction(Cache, &Fix, BrokenFix);
129 InstallAction(Cache[Pkg].CandidateVerIter(Cache));
130 InstallAction.doAutoInstall();
131 } else
132 return AllowFail;
133
134 return true;
135 }
136 /*}}}*/
137
138 // FIXME: move into more generic code (metaindex ?)
139 std::string MetaIndexFileName(metaIndex *metaindex)
140 {
141 // FIXME: this cast is the horror, the horror
142 debReleaseIndex *r = (debReleaseIndex*)metaindex;
143
144 // see if we have a InRelease file
145 std::string PathInRelease = r->MetaIndexFile("InRelease");
146 if (FileExists(PathInRelease))
147 return PathInRelease;
148
149 // and if not return the normal one
150 return r->MetaIndexFile("Release");
151 }
152
153 std::string GetReleaseForSourceRecord(pkgSourceList *SrcList,
154 pkgSrcRecords::Parser *Parse)
155 {
156 // try to find release
157 const pkgIndexFile& SI = Parse->Index();
158 for (pkgSourceList::const_iterator S = SrcList->begin();
159 S != SrcList->end(); ++S)
160 {
161 vector<pkgIndexFile *> *Indexes = (*S)->GetIndexFiles();
162 for (vector<pkgIndexFile *>::const_iterator IF = Indexes->begin();
163 IF != Indexes->end(); ++IF)
164 {
165 if (&SI == (*IF))
166 {
167 std::string path = MetaIndexFileName(*S);
168 indexRecords records;
169 records.Load(path);
170 return records.GetSuite();
171 }
172 }
173 }
174 return "";
175 }
176
177
178 // FindSrc - Find a source record /*{{{*/
179 // ---------------------------------------------------------------------
180 /* */
181 pkgSrcRecords::Parser *FindSrc(const char *Name,pkgRecords &Recs,
182 pkgSrcRecords &SrcRecs,string &Src,
183 CacheFile &CacheFile)
184 {
185 string VerTag;
186 string RelTag = _config->Find("APT::Default-Release");
187 string TmpSrc = Name;
188 pkgDepCache *Cache = CacheFile.GetDepCache();
189
190 // extract the version/release from the pkgname
191 const size_t found = TmpSrc.find_last_of("/=");
192 if (found != string::npos) {
193 if (TmpSrc[found] == '/')
194 RelTag = TmpSrc.substr(found+1);
195 else
196 VerTag = TmpSrc.substr(found+1);
197 TmpSrc = TmpSrc.substr(0,found);
198 }
199
200 /* Lookup the version of the package we would install if we were to
201 install a version and determine the source package name, then look
202 in the archive for a source package of the same name. */
203 bool MatchSrcOnly = _config->FindB("APT::Get::Only-Source");
204 const pkgCache::PkgIterator Pkg = Cache->FindPkg(TmpSrc);
205 if (MatchSrcOnly == false && Pkg.end() == false)
206 {
207 if(VerTag.empty() == false || RelTag.empty() == false)
208 {
209 bool fuzzy = false;
210 // we have a default release, try to locate the pkg. we do it like
211 // this because GetCandidateVer() will not "downgrade", that means
212 // "apt-get source -t stable apt" won't work on a unstable system
213 for (pkgCache::VerIterator Ver = Pkg.VersionList();; ++Ver)
214 {
215 // try first only exact matches, later fuzzy matches
216 if (Ver.end() == true)
217 {
218 if (fuzzy == true)
219 break;
220 fuzzy = true;
221 Ver = Pkg.VersionList();
222 // exit right away from the Pkg.VersionList() loop if we
223 // don't have any versions
224 if (Ver.end() == true)
225 break;
226 }
227 // We match against a concrete version (or a part of this version)
228 if (VerTag.empty() == false &&
229 (fuzzy == true || Cache->VS().CmpVersion(VerTag, Ver.VerStr()) != 0) && // exact match
230 (fuzzy == false || strncmp(VerTag.c_str(), Ver.VerStr(), VerTag.size()) != 0)) // fuzzy match
231 continue;
232
233 for (pkgCache::VerFileIterator VF = Ver.FileList();
234 VF.end() == false; ++VF)
235 {
236 /* If this is the status file, and the current version is not the
237 version in the status file (ie it is not installed, or somesuch)
238 then it is not a candidate for installation, ever. This weeds
239 out bogus entries that may be due to config-file states, or
240 other. */
241 if ((VF.File()->Flags & pkgCache::Flag::NotSource) ==
242 pkgCache::Flag::NotSource && Pkg.CurrentVer() != Ver)
243 continue;
244
245 // or we match against a release
246 if(VerTag.empty() == false ||
247 (VF.File().Archive() != 0 && VF.File().Archive() == RelTag) ||
248 (VF.File().Codename() != 0 && VF.File().Codename() == RelTag))
249 {
250 pkgRecords::Parser &Parse = Recs.Lookup(VF);
251 Src = Parse.SourcePkg();
252 // no SourcePkg name, so it is the "binary" name
253 if (Src.empty() == true)
254 Src = TmpSrc;
255 // the Version we have is possibly fuzzy or includes binUploads,
256 // so we use the Version of the SourcePkg (empty if same as package)
257 VerTag = Parse.SourceVer();
258 if (VerTag.empty() == true)
259 VerTag = Ver.VerStr();
260 break;
261 }
262 }
263 if (Src.empty() == false)
264 break;
265 }
266 }
267 if (Src.empty() == true)
268 {
269 // if we don't have found a fitting package yet so we will
270 // choose a good candidate and proceed with that.
271 // Maybe we will find a source later on with the right VerTag
272 // or RelTag
273 pkgCache::VerIterator Ver = Cache->GetCandidateVer(Pkg);
274 if (Ver.end() == false)
275 {
276 pkgRecords::Parser &Parse = Recs.Lookup(Ver.FileList());
277 Src = Parse.SourcePkg();
278 if (VerTag.empty() == true)
279 VerTag = Parse.SourceVer();
280 }
281 }
282 }
283
284 if (Src.empty() == true)
285 {
286 Src = TmpSrc;
287 }
288 else
289 {
290 /* if we have a source pkg name, make sure to only search
291 for srcpkg names, otherwise apt gets confused if there
292 is a binary package "pkg1" and a source package "pkg1"
293 with the same name but that comes from different packages */
294 MatchSrcOnly = true;
295 if (Src != TmpSrc)
296 {
297 ioprintf(c1out, _("Picking '%s' as source package instead of '%s'\n"), Src.c_str(), TmpSrc.c_str());
298 }
299 }
300
301 // The best hit
302 pkgSrcRecords::Parser *Last = 0;
303 unsigned long Offset = 0;
304 string Version;
305 pkgSourceList *SrcList = CacheFile.GetSourceList();
306
307 /* Iterate over all of the hits, which includes the resulting
308 binary packages in the search */
309 pkgSrcRecords::Parser *Parse;
310 while (true)
311 {
312 SrcRecs.Restart();
313 while ((Parse = SrcRecs.Find(Src.c_str(), MatchSrcOnly)) != 0)
314 {
315 const string Ver = Parse->Version();
316
317 // See if we need to look for a specific release tag
318 if (RelTag != "")
319 {
320 const string Rel = GetReleaseForSourceRecord(SrcList, Parse);
321
322 if (Rel == RelTag)
323 {
324 ioprintf(c1out, "Selectied version '%s' (%s) for %s\n",
325 Ver.c_str(), RelTag.c_str(), Src.c_str());
326 Last = Parse;
327 Offset = Parse->Offset();
328 break;
329 }
330 }
331
332 // Ignore all versions which doesn't fit
333 if (VerTag.empty() == false &&
334 Cache->VS().CmpVersion(VerTag, Ver) != 0) // exact match
335 continue;
336
337 // Newer version or an exact match? Save the hit
338 if (Last == 0 || Cache->VS().CmpVersion(Version,Ver) < 0) {
339 Last = Parse;
340 Offset = Parse->Offset();
341 Version = Ver;
342 }
343
344 // was the version check above an exact match?
345 // If so, we don't need to look further
346 if (VerTag.empty() == false && (VerTag == Ver))
347 break;
348 }
349 if (Last != 0 || VerTag.empty() == true)
350 break;
351 _error->Error(_("Ignore unavailable version '%s' of package '%s'"), VerTag.c_str(), TmpSrc.c_str());
352 return 0;
353 }
354
355 if (Last == 0 || Last->Jump(Offset) == false)
356 return 0;
357
358 return Last;
359 }
360 /*}}}*/
361 /* mark packages as automatically/manually installed. {{{*/
362 bool DoMarkAuto(CommandLine &CmdL)
363 {
364 bool Action = true;
365 int AutoMarkChanged = 0;
366 OpTextProgress progress;
367 CacheFile Cache;
368 if (Cache.Open() == false)
369 return false;
370
371 if (strcasecmp(CmdL.FileList[0],"markauto") == 0)
372 Action = true;
373 else if (strcasecmp(CmdL.FileList[0],"unmarkauto") == 0)
374 Action = false;
375
376 for (const char **I = CmdL.FileList + 1; *I != 0; I++)
377 {
378 const char *S = *I;
379 // Locate the package
380 pkgCache::PkgIterator Pkg = Cache->FindPkg(S);
381 if (Pkg.end() == true) {
382 return _error->Error(_("Couldn't find package %s"),S);
383 }
384 else
385 {
386 if (!Action)
387 ioprintf(c1out,_("%s set to manually installed.\n"), Pkg.Name());
388 else
389 ioprintf(c1out,_("%s set to automatically installed.\n"),
390 Pkg.Name());
391
392 Cache->MarkAuto(Pkg,Action);
393 AutoMarkChanged++;
394 }
395 }
396
397 _error->Notice(_("This command is deprecated. Please use 'apt-mark auto' and 'apt-mark manual' instead."));
398
399 if (AutoMarkChanged && ! _config->FindB("APT::Get::Simulate",false))
400 return Cache->writeStateFile(NULL);
401 return false;
402 }
403 /*}}}*/
404 // DoDSelectUpgrade - Do an upgrade by following dselects selections /*{{{*/
405 // ---------------------------------------------------------------------
406 /* Follows dselect's selections */
407 bool DoDSelectUpgrade(CommandLine &CmdL)
408 {
409 CacheFile Cache;
410 if (Cache.OpenForInstall() == false || Cache.CheckDeps() == false)
411 return false;
412
413 pkgDepCache::ActionGroup group(Cache);
414
415 // Install everything with the install flag set
416 pkgCache::PkgIterator I = Cache->PkgBegin();
417 for (;I.end() != true; ++I)
418 {
419 /* Install the package only if it is a new install, the autoupgrader
420 will deal with the rest */
421 if (I->SelectedState == pkgCache::State::Install)
422 Cache->MarkInstall(I,false);
423 }
424
425 /* Now install their deps too, if we do this above then order of
426 the status file is significant for | groups */
427 for (I = Cache->PkgBegin();I.end() != true; ++I)
428 {
429 /* Install the package only if it is a new install, the autoupgrader
430 will deal with the rest */
431 if (I->SelectedState == pkgCache::State::Install)
432 Cache->MarkInstall(I,true);
433 }
434
435 // Apply erasures now, they override everything else.
436 for (I = Cache->PkgBegin();I.end() != true; ++I)
437 {
438 // Remove packages
439 if (I->SelectedState == pkgCache::State::DeInstall ||
440 I->SelectedState == pkgCache::State::Purge)
441 Cache->MarkDelete(I,I->SelectedState == pkgCache::State::Purge);
442 }
443
444 /* Resolve any problems that dselect created, allupgrade cannot handle
445 such things. We do so quite agressively too.. */
446 if (Cache->BrokenCount() != 0)
447 {
448 pkgProblemResolver Fix(Cache);
449
450 // Hold back held packages.
451 if (_config->FindB("APT::Ignore-Hold",false) == false)
452 {
453 for (pkgCache::PkgIterator I = Cache->PkgBegin(); I.end() == false; ++I)
454 {
455 if (I->SelectedState == pkgCache::State::Hold)
456 {
457 Fix.Protect(I);
458 Cache->MarkKeep(I);
459 }
460 }
461 }
462
463 if (Fix.Resolve() == false)
464 {
465 ShowBroken(c1out,Cache,false);
466 return _error->Error(_("Internal error, problem resolver broke stuff"));
467 }
468 }
469
470 // Now upgrade everything
471 if (pkgAllUpgrade(Cache) == false)
472 {
473 ShowBroken(c1out,Cache,false);
474 return _error->Error(_("Internal error, problem resolver broke stuff"));
475 }
476
477 return InstallPackages(Cache,false);
478 }
479 /*}}}*/
480 // DoClean - Remove download archives /*{{{*/
481 // ---------------------------------------------------------------------
482 /* */
483 bool DoClean(CommandLine &CmdL)
484 {
485 std::string const archivedir = _config->FindDir("Dir::Cache::archives");
486 std::string const pkgcache = _config->FindFile("Dir::cache::pkgcache");
487 std::string const srcpkgcache = _config->FindFile("Dir::cache::srcpkgcache");
488
489 if (_config->FindB("APT::Get::Simulate") == true)
490 {
491 cout << "Del " << archivedir << "* " << archivedir << "partial/*"<< endl
492 << "Del " << pkgcache << " " << srcpkgcache << endl;
493 return true;
494 }
495
496 // Lock the archive directory
497 FileFd Lock;
498 if (_config->FindB("Debug::NoLocking",false) == false)
499 {
500 int lock_fd = GetLock(archivedir + "lock");
501 if (lock_fd < 0)
502 return _error->Error(_("Unable to lock the download directory"));
503 Lock.Fd(lock_fd);
504 }
505
506 pkgAcquire Fetcher;
507 Fetcher.Clean(archivedir);
508 Fetcher.Clean(archivedir + "partial/");
509
510 pkgCacheFile::RemoveCaches();
511
512 return true;
513 }
514 /*}}}*/
515 // DoAutoClean - Smartly remove downloaded archives /*{{{*/
516 // ---------------------------------------------------------------------
517 /* This is similar to clean but it only purges things that cannot be
518 downloaded, that is old versions of cached packages. */
519 class LogCleaner : public pkgArchiveCleaner
520 {
521 protected:
522 virtual void Erase(const char *File,string Pkg,string Ver,struct stat &St)
523 {
524 c1out << "Del " << Pkg << " " << Ver << " [" << SizeToStr(St.st_size) << "B]" << endl;
525
526 if (_config->FindB("APT::Get::Simulate") == false)
527 unlink(File);
528 };
529 };
530
531 bool DoAutoClean(CommandLine &CmdL)
532 {
533 // Lock the archive directory
534 FileFd Lock;
535 if (_config->FindB("Debug::NoLocking",false) == false)
536 {
537 int lock_fd = GetLock(_config->FindDir("Dir::Cache::Archives") + "lock");
538 if (lock_fd < 0)
539 return _error->Error(_("Unable to lock the download directory"));
540 Lock.Fd(lock_fd);
541 }
542
543 CacheFile Cache;
544 if (Cache.Open() == false)
545 return false;
546
547 LogCleaner Cleaner;
548
549 return Cleaner.Go(_config->FindDir("Dir::Cache::archives"),*Cache) &&
550 Cleaner.Go(_config->FindDir("Dir::Cache::archives") + "partial/",*Cache);
551 }
552 /*}}}*/
553 // DoDownload - download a binary /*{{{*/
554 // ---------------------------------------------------------------------
555 bool DoDownload(CommandLine &CmdL)
556 {
557 CacheFile Cache;
558 if (Cache.ReadOnlyOpen() == false)
559 return false;
560
561 APT::CacheSetHelper helper(c0out);
562 APT::VersionList verset = APT::VersionList::FromCommandLine(Cache,
563 CmdL.FileList + 1, APT::VersionList::CANDIDATE, helper);
564
565 if (verset.empty() == true)
566 return false;
567
568 AcqTextStatus Stat(ScreenWidth, _config->FindI("quiet", 0));
569 pkgAcquire Fetcher;
570 if (Fetcher.Setup(&Stat) == false)
571 return false;
572
573 pkgRecords Recs(Cache);
574 pkgSourceList *SrcList = Cache.GetSourceList();
575
576 // reuse the usual acquire methods for deb files, but don't drop them into
577 // the usual directories - keep everything in the current directory
578 std::vector<std::string> storefile(verset.size());
579 std::string const cwd = SafeGetCWD();
580 _config->Set("Dir::Cache::Archives", cwd);
581 int i = 0;
582 for (APT::VersionList::const_iterator Ver = verset.begin();
583 Ver != verset.end(); ++Ver, ++i)
584 {
585 pkgAcquire::Item *I = new pkgAcqArchive(&Fetcher, SrcList, &Recs, *Ver, storefile[i]);
586 std::string const filename = cwd + flNotDir(storefile[i]);
587 storefile[i].assign(filename);
588 I->DestFile.assign(filename);
589 }
590
591 // Just print out the uris and exit if the --print-uris flag was used
592 if (_config->FindB("APT::Get::Print-URIs") == true)
593 {
594 pkgAcquire::UriIterator I = Fetcher.UriBegin();
595 for (; I != Fetcher.UriEnd(); ++I)
596 cout << '\'' << I->URI << "' " << flNotDir(I->Owner->DestFile) << ' ' <<
597 I->Owner->FileSize << ' ' << I->Owner->HashSum() << endl;
598 return true;
599 }
600
601 if (_error->PendingError() == true || CheckAuth(Fetcher, false) == false)
602 return false;
603
604 bool Failed = false;
605 if (AcquireRun(Fetcher, 0, &Failed, NULL) == false)
606 return false;
607
608 // copy files in local sources to the current directory
609 for (pkgAcquire::ItemIterator I = Fetcher.ItemsBegin(); I != Fetcher.ItemsEnd(); ++I)
610 if ((*I)->Local == true && (*I)->Status == pkgAcquire::Item::StatDone)
611 {
612 std::string const filename = cwd + flNotDir((*I)->DestFile);
613 std::ifstream src((*I)->DestFile.c_str(), std::ios::binary);
614 std::ofstream dst(filename.c_str(), std::ios::binary);
615 dst << src.rdbuf();
616 }
617
618 return Failed == false;
619 }
620 /*}}}*/
621 // DoCheck - Perform the check operation /*{{{*/
622 // ---------------------------------------------------------------------
623 /* Opening automatically checks the system, this command is mostly used
624 for debugging */
625 bool DoCheck(CommandLine &CmdL)
626 {
627 CacheFile Cache;
628 Cache.Open();
629 Cache.CheckDeps();
630
631 return true;
632 }
633 /*}}}*/
634 // DoSource - Fetch a source archive /*{{{*/
635 // ---------------------------------------------------------------------
636 /* Fetch souce packages */
637 struct DscFile
638 {
639 string Package;
640 string Version;
641 string Dsc;
642 };
643
644 bool DoSource(CommandLine &CmdL)
645 {
646 CacheFile Cache;
647 if (Cache.Open(false) == false)
648 return false;
649
650 if (CmdL.FileSize() <= 1)
651 return _error->Error(_("Must specify at least one package to fetch source for"));
652
653 // Read the source list
654 if (Cache.BuildSourceList() == false)
655 return false;
656 pkgSourceList *List = Cache.GetSourceList();
657
658 // Create the text record parsers
659 pkgRecords Recs(Cache);
660 pkgSrcRecords SrcRecs(*List);
661 if (_error->PendingError() == true)
662 return false;
663
664 // Create the download object
665 AcqTextStatus Stat(ScreenWidth,_config->FindI("quiet",0));
666 pkgAcquire Fetcher;
667 Fetcher.SetLog(&Stat);
668
669 DscFile *Dsc = new DscFile[CmdL.FileSize()];
670
671 // insert all downloaded uris into this set to avoid downloading them
672 // twice
673 set<string> queued;
674
675 // Diff only mode only fetches .diff files
676 bool const diffOnly = _config->FindB("APT::Get::Diff-Only", false);
677 // Tar only mode only fetches .tar files
678 bool const tarOnly = _config->FindB("APT::Get::Tar-Only", false);
679 // Dsc only mode only fetches .dsc files
680 bool const dscOnly = _config->FindB("APT::Get::Dsc-Only", false);
681
682 // Load the requestd sources into the fetcher
683 unsigned J = 0;
684 for (const char **I = CmdL.FileList + 1; *I != 0; I++, J++)
685 {
686 string Src;
687 pkgSrcRecords::Parser *Last = FindSrc(*I,Recs,SrcRecs,Src,Cache);
688
689 if (Last == 0) {
690 delete[] Dsc;
691 return _error->Error(_("Unable to find a source package for %s"),Src.c_str());
692 }
693
694 string srec = Last->AsStr();
695 string::size_type pos = srec.find("\nVcs-");
696 while (pos != string::npos)
697 {
698 pos += strlen("\nVcs-");
699 string vcs = srec.substr(pos,srec.find(":",pos)-pos);
700 if(vcs == "Browser")
701 {
702 pos = srec.find("\nVcs-", pos);
703 continue;
704 }
705 pos += vcs.length()+2;
706 string::size_type epos = srec.find("\n", pos);
707 string uri = srec.substr(pos,epos-pos).c_str();
708 ioprintf(c1out, _("NOTICE: '%s' packaging is maintained in "
709 "the '%s' version control system at:\n"
710 "%s\n"),
711 Src.c_str(), vcs.c_str(), uri.c_str());
712 if(vcs == "Bzr")
713 ioprintf(c1out,_("Please use:\n"
714 "bzr branch %s\n"
715 "to retrieve the latest (possibly unreleased) "
716 "updates to the package.\n"),
717 uri.c_str());
718 break;
719 }
720
721 // Back track
722 vector<pkgSrcRecords::File> Lst;
723 if (Last->Files(Lst) == false) {
724 delete[] Dsc;
725 return false;
726 }
727
728 // Load them into the fetcher
729 for (vector<pkgSrcRecords::File>::const_iterator I = Lst.begin();
730 I != Lst.end(); ++I)
731 {
732 // Try to guess what sort of file it is we are getting.
733 if (I->Type == "dsc")
734 {
735 Dsc[J].Package = Last->Package();
736 Dsc[J].Version = Last->Version();
737 Dsc[J].Dsc = flNotDir(I->Path);
738 }
739
740 // Handle the only options so that multiple can be used at once
741 if (diffOnly == true || tarOnly == true || dscOnly == true)
742 {
743 if ((diffOnly == true && I->Type == "diff") ||
744 (tarOnly == true && I->Type == "tar") ||
745 (dscOnly == true && I->Type == "dsc"))
746 ; // Fine, we want this file downloaded
747 else
748 continue;
749 }
750
751 // don't download the same uri twice (should this be moved to
752 // the fetcher interface itself?)
753 if(queued.find(Last->Index().ArchiveURI(I->Path)) != queued.end())
754 continue;
755 queued.insert(Last->Index().ArchiveURI(I->Path));
756
757 // check if we have a file with that md5 sum already localy
758 if(!I->MD5Hash.empty() && FileExists(flNotDir(I->Path)))
759 {
760 FileFd Fd(flNotDir(I->Path), FileFd::ReadOnly);
761 MD5Summation sum;
762 sum.AddFD(Fd.Fd(), Fd.Size());
763 Fd.Close();
764 if((string)sum.Result() == I->MD5Hash)
765 {
766 ioprintf(c1out,_("Skipping already downloaded file '%s'\n"),
767 flNotDir(I->Path).c_str());
768 continue;
769 }
770 }
771
772 new pkgAcqFile(&Fetcher,Last->Index().ArchiveURI(I->Path),
773 I->MD5Hash,I->Size,
774 Last->Index().SourceInfo(*Last,*I),Src);
775 }
776 }
777
778 // Display statistics
779 unsigned long long FetchBytes = Fetcher.FetchNeeded();
780 unsigned long long FetchPBytes = Fetcher.PartialPresent();
781 unsigned long long DebBytes = Fetcher.TotalNeeded();
782
783 // Check for enough free space
784 struct statvfs Buf;
785 string OutputDir = ".";
786 if (statvfs(OutputDir.c_str(),&Buf) != 0) {
787 delete[] Dsc;
788 if (errno == EOVERFLOW)
789 return _error->WarningE("statvfs",_("Couldn't determine free space in %s"),
790 OutputDir.c_str());
791 else
792 return _error->Errno("statvfs",_("Couldn't determine free space in %s"),
793 OutputDir.c_str());
794 } else if (unsigned(Buf.f_bfree) < (FetchBytes - FetchPBytes)/Buf.f_bsize)
795 {
796 struct statfs Stat;
797 if (statfs(OutputDir.c_str(),&Stat) != 0
798 #if HAVE_STRUCT_STATFS_F_TYPE
799 || unsigned(Stat.f_type) != RAMFS_MAGIC
800 #endif
801 ) {
802 delete[] Dsc;
803 return _error->Error(_("You don't have enough free space in %s"),
804 OutputDir.c_str());
805 }
806 }
807
808 // Number of bytes
809 if (DebBytes != FetchBytes)
810 //TRANSLATOR: The required space between number and unit is already included
811 // in the replacement strings, so %sB will be correctly translate in e.g. 1,5 MB
812 ioprintf(c1out,_("Need to get %sB/%sB of source archives.\n"),
813 SizeToStr(FetchBytes).c_str(),SizeToStr(DebBytes).c_str());
814 else
815 //TRANSLATOR: The required space between number and unit is already included
816 // in the replacement string, so %sB will be correctly translate in e.g. 1,5 MB
817 ioprintf(c1out,_("Need to get %sB of source archives.\n"),
818 SizeToStr(DebBytes).c_str());
819
820 if (_config->FindB("APT::Get::Simulate",false) == true)
821 {
822 for (unsigned I = 0; I != J; I++)
823 ioprintf(cout,_("Fetch source %s\n"),Dsc[I].Package.c_str());
824 delete[] Dsc;
825 return true;
826 }
827
828 // Just print out the uris an exit if the --print-uris flag was used
829 if (_config->FindB("APT::Get::Print-URIs") == true)
830 {
831 pkgAcquire::UriIterator I = Fetcher.UriBegin();
832 for (; I != Fetcher.UriEnd(); ++I)
833 cout << '\'' << I->URI << "' " << flNotDir(I->Owner->DestFile) << ' ' <<
834 I->Owner->FileSize << ' ' << I->Owner->HashSum() << endl;
835 delete[] Dsc;
836 return true;
837 }
838
839 // Run it
840 bool Failed = false;
841 if (AcquireRun(Fetcher, 0, &Failed, NULL) == false || Failed == true)
842 {
843 delete[] Dsc;
844 return _error->Error(_("Failed to fetch some archives."));
845 }
846
847 if (_config->FindB("APT::Get::Download-only",false) == true)
848 {
849 c1out << _("Download complete and in download only mode") << endl;
850 delete[] Dsc;
851 return true;
852 }
853
854 // Unpack the sources
855 pid_t Process = ExecFork();
856
857 if (Process == 0)
858 {
859 bool const fixBroken = _config->FindB("APT::Get::Fix-Broken", false);
860 for (unsigned I = 0; I != J; ++I)
861 {
862 string Dir = Dsc[I].Package + '-' + Cache->VS().UpstreamVersion(Dsc[I].Version.c_str());
863
864 // Diff only mode only fetches .diff files
865 if (_config->FindB("APT::Get::Diff-Only",false) == true ||
866 _config->FindB("APT::Get::Tar-Only",false) == true ||
867 Dsc[I].Dsc.empty() == true)
868 continue;
869
870 // See if the package is already unpacked
871 struct stat Stat;
872 if (fixBroken == false && stat(Dir.c_str(),&Stat) == 0 &&
873 S_ISDIR(Stat.st_mode) != 0)
874 {
875 ioprintf(c0out ,_("Skipping unpack of already unpacked source in %s\n"),
876 Dir.c_str());
877 }
878 else
879 {
880 // Call dpkg-source
881 char S[500];
882 snprintf(S,sizeof(S),"%s -x %s",
883 _config->Find("Dir::Bin::dpkg-source","dpkg-source").c_str(),
884 Dsc[I].Dsc.c_str());
885 if (system(S) != 0)
886 {
887 fprintf(stderr,_("Unpack command '%s' failed.\n"),S);
888 fprintf(stderr,_("Check if the 'dpkg-dev' package is installed.\n"));
889 _exit(1);
890 }
891 }
892
893 // Try to compile it with dpkg-buildpackage
894 if (_config->FindB("APT::Get::Compile",false) == true)
895 {
896 string buildopts = _config->Find("APT::Get::Host-Architecture");
897 if (buildopts.empty() == false)
898 buildopts = "-a" + buildopts + " ";
899 buildopts.append(_config->Find("DPkg::Build-Options","-b -uc"));
900
901 // Call dpkg-buildpackage
902 char S[500];
903 snprintf(S,sizeof(S),"cd %s && %s %s",
904 Dir.c_str(),
905 _config->Find("Dir::Bin::dpkg-buildpackage","dpkg-buildpackage").c_str(),
906 buildopts.c_str());
907
908 if (system(S) != 0)
909 {
910 fprintf(stderr,_("Build command '%s' failed.\n"),S);
911 _exit(1);
912 }
913 }
914 }
915
916 _exit(0);
917 }
918 delete[] Dsc;
919
920 // Wait for the subprocess
921 int Status = 0;
922 while (waitpid(Process,&Status,0) != Process)
923 {
924 if (errno == EINTR)
925 continue;
926 return _error->Errno("waitpid","Couldn't wait for subprocess");
927 }
928
929 if (WIFEXITED(Status) == 0 || WEXITSTATUS(Status) != 0)
930 return _error->Error(_("Child process failed"));
931
932 return true;
933 }
934 /*}}}*/
935 // DoBuildDep - Install/removes packages to satisfy build dependencies /*{{{*/
936 // ---------------------------------------------------------------------
937 /* This function will look at the build depends list of the given source
938 package and install the necessary packages to make it true, or fail. */
939 bool DoBuildDep(CommandLine &CmdL)
940 {
941 CacheFile Cache;
942
943 _config->Set("APT::Install-Recommends", false);
944
945 if (Cache.Open(true) == false)
946 return false;
947
948 if (CmdL.FileSize() <= 1)
949 return _error->Error(_("Must specify at least one package to check builddeps for"));
950
951 // Read the source list
952 if (Cache.BuildSourceList() == false)
953 return false;
954 pkgSourceList *List = Cache.GetSourceList();
955
956 // Create the text record parsers
957 pkgRecords Recs(Cache);
958 pkgSrcRecords SrcRecs(*List);
959 if (_error->PendingError() == true)
960 return false;
961
962 // Create the download object
963 AcqTextStatus Stat(ScreenWidth,_config->FindI("quiet",0));
964 pkgAcquire Fetcher;
965 if (Fetcher.Setup(&Stat) == false)
966 return false;
967
968 bool StripMultiArch;
969 string hostArch = _config->Find("APT::Get::Host-Architecture");
970 if (hostArch.empty() == false)
971 {
972 std::vector<std::string> archs = APT::Configuration::getArchitectures();
973 if (std::find(archs.begin(), archs.end(), hostArch) == archs.end())
974 return _error->Error(_("No architecture information available for %s. See apt.conf(5) APT::Architectures for setup"), hostArch.c_str());
975 StripMultiArch = false;
976 }
977 else
978 StripMultiArch = true;
979
980 unsigned J = 0;
981 for (const char **I = CmdL.FileList + 1; *I != 0; I++, J++)
982 {
983 string Src;
984 pkgSrcRecords::Parser *Last = FindSrc(*I,Recs,SrcRecs,Src,Cache);
985 if (Last == 0)
986 return _error->Error(_("Unable to find a source package for %s"),Src.c_str());
987
988 // Process the build-dependencies
989 vector<pkgSrcRecords::Parser::BuildDepRec> BuildDeps;
990 // FIXME: Can't specify architecture to use for [wildcard] matching, so switch default arch temporary
991 if (hostArch.empty() == false)
992 {
993 std::string nativeArch = _config->Find("APT::Architecture");
994 _config->Set("APT::Architecture", hostArch);
995 bool Success = Last->BuildDepends(BuildDeps, _config->FindB("APT::Get::Arch-Only", false), StripMultiArch);
996 _config->Set("APT::Architecture", nativeArch);
997 if (Success == false)
998 return _error->Error(_("Unable to get build-dependency information for %s"),Src.c_str());
999 }
1000 else if (Last->BuildDepends(BuildDeps, _config->FindB("APT::Get::Arch-Only", false), StripMultiArch) == false)
1001 return _error->Error(_("Unable to get build-dependency information for %s"),Src.c_str());
1002
1003 // Also ensure that build-essential packages are present
1004 Configuration::Item const *Opts = _config->Tree("APT::Build-Essential");
1005 if (Opts)
1006 Opts = Opts->Child;
1007 for (; Opts; Opts = Opts->Next)
1008 {
1009 if (Opts->Value.empty() == true)
1010 continue;
1011
1012 pkgSrcRecords::Parser::BuildDepRec rec;
1013 rec.Package = Opts->Value;
1014 rec.Type = pkgSrcRecords::Parser::BuildDependIndep;
1015 rec.Op = 0;
1016 BuildDeps.push_back(rec);
1017 }
1018
1019 if (BuildDeps.empty() == true)
1020 {
1021 ioprintf(c1out,_("%s has no build depends.\n"),Src.c_str());
1022 continue;
1023 }
1024
1025 // Install the requested packages
1026 vector <pkgSrcRecords::Parser::BuildDepRec>::iterator D;
1027 pkgProblemResolver Fix(Cache);
1028 bool skipAlternatives = false; // skip remaining alternatives in an or group
1029 for (D = BuildDeps.begin(); D != BuildDeps.end(); ++D)
1030 {
1031 bool hasAlternatives = (((*D).Op & pkgCache::Dep::Or) == pkgCache::Dep::Or);
1032
1033 if (skipAlternatives == true)
1034 {
1035 /*
1036 * if there are alternatives, we've already picked one, so skip
1037 * the rest
1038 *
1039 * TODO: this means that if there's a build-dep on A|B and B is
1040 * installed, we'll still try to install A; more importantly,
1041 * if A is currently broken, we cannot go back and try B. To fix
1042 * this would require we do a Resolve cycle for each package we
1043 * add to the install list. Ugh
1044 */
1045 if (!hasAlternatives)
1046 skipAlternatives = false; // end of or group
1047 continue;
1048 }
1049
1050 if ((*D).Type == pkgSrcRecords::Parser::BuildConflict ||
1051 (*D).Type == pkgSrcRecords::Parser::BuildConflictIndep)
1052 {
1053 pkgCache::GrpIterator Grp = Cache->FindGrp((*D).Package);
1054 // Build-conflicts on unknown packages are silently ignored
1055 if (Grp.end() == true)
1056 continue;
1057
1058 for (pkgCache::PkgIterator Pkg = Grp.PackageList(); Pkg.end() == false; Pkg = Grp.NextPkg(Pkg))
1059 {
1060 pkgCache::VerIterator IV = (*Cache)[Pkg].InstVerIter(*Cache);
1061 /*
1062 * Remove if we have an installed version that satisfies the
1063 * version criteria
1064 */
1065 if (IV.end() == false &&
1066 Cache->VS().CheckDep(IV.VerStr(),(*D).Op,(*D).Version.c_str()) == true)
1067 TryToInstallBuildDep(Pkg,Cache,Fix,true,false);
1068 }
1069 }
1070 else // BuildDep || BuildDepIndep
1071 {
1072 if (_config->FindB("Debug::BuildDeps",false) == true)
1073 cout << "Looking for " << (*D).Package << "...\n";
1074
1075 pkgCache::PkgIterator Pkg;
1076
1077 // Cross-Building?
1078 if (StripMultiArch == false && D->Type != pkgSrcRecords::Parser::BuildDependIndep)
1079 {
1080 size_t const colon = D->Package.find(":");
1081 if (colon != string::npos)
1082 {
1083 if (strcmp(D->Package.c_str() + colon, ":any") == 0 || strcmp(D->Package.c_str() + colon, ":native") == 0)
1084 Pkg = Cache->FindPkg(D->Package.substr(0,colon));
1085 else
1086 Pkg = Cache->FindPkg(D->Package);
1087 }
1088 else
1089 Pkg = Cache->FindPkg(D->Package, hostArch);
1090
1091 // a bad version either is invalid or doesn't satify dependency
1092 #define BADVER(Ver) (Ver.end() == true || \
1093 (D->Version.empty() == false && \
1094 Cache->VS().CheckDep(Ver.VerStr(),D->Op,D->Version.c_str()) == false))
1095
1096 APT::VersionList verlist;
1097 if (Pkg.end() == false)
1098 {
1099 pkgCache::VerIterator Ver = (*Cache)[Pkg].InstVerIter(*Cache);
1100 if (BADVER(Ver) == false)
1101 verlist.insert(Ver);
1102 Ver = (*Cache)[Pkg].CandidateVerIter(*Cache);
1103 if (BADVER(Ver) == false)
1104 verlist.insert(Ver);
1105 }
1106 if (verlist.empty() == true)
1107 {
1108 pkgCache::PkgIterator BuildPkg = Cache->FindPkg(D->Package, "native");
1109 if (BuildPkg.end() == false && Pkg != BuildPkg)
1110 {
1111 pkgCache::VerIterator Ver = (*Cache)[BuildPkg].InstVerIter(*Cache);
1112 if (BADVER(Ver) == false)
1113 verlist.insert(Ver);
1114 Ver = (*Cache)[BuildPkg].CandidateVerIter(*Cache);
1115 if (BADVER(Ver) == false)
1116 verlist.insert(Ver);
1117 }
1118 }
1119 #undef BADVER
1120
1121 string forbidden;
1122 // We need to decide if host or build arch, so find a version we can look at
1123 APT::VersionList::const_iterator Ver = verlist.begin();
1124 for (; Ver != verlist.end(); ++Ver)
1125 {
1126 forbidden.clear();
1127 if (Ver->MultiArch == pkgCache::Version::None || Ver->MultiArch == pkgCache::Version::All)
1128 {
1129 if (colon == string::npos)
1130 Pkg = Ver.ParentPkg().Group().FindPkg(hostArch);
1131 else if (strcmp(D->Package.c_str() + colon, ":any") == 0)
1132 forbidden = "Multi-Arch: none";
1133 else if (strcmp(D->Package.c_str() + colon, ":native") == 0)
1134 Pkg = Ver.ParentPkg().Group().FindPkg("native");
1135 }
1136 else if (Ver->MultiArch == pkgCache::Version::Same)
1137 {
1138 if (colon == string::npos)
1139 Pkg = Ver.ParentPkg().Group().FindPkg(hostArch);
1140 else if (strcmp(D->Package.c_str() + colon, ":any") == 0)
1141 forbidden = "Multi-Arch: same";
1142 else if (strcmp(D->Package.c_str() + colon, ":native") == 0)
1143 Pkg = Ver.ParentPkg().Group().FindPkg("native");
1144 }
1145 else if ((Ver->MultiArch & pkgCache::Version::Foreign) == pkgCache::Version::Foreign)
1146 {
1147 if (colon == string::npos)
1148 Pkg = Ver.ParentPkg().Group().FindPkg("native");
1149 else if (strcmp(D->Package.c_str() + colon, ":any") == 0 ||
1150 strcmp(D->Package.c_str() + colon, ":native") == 0)
1151 forbidden = "Multi-Arch: foreign";
1152 }
1153 else if ((Ver->MultiArch & pkgCache::Version::Allowed) == pkgCache::Version::Allowed)
1154 {
1155 if (colon == string::npos)
1156 Pkg = Ver.ParentPkg().Group().FindPkg(hostArch);
1157 else if (strcmp(D->Package.c_str() + colon, ":any") == 0)
1158 {
1159 // prefer any installed over preferred non-installed architectures
1160 pkgCache::GrpIterator Grp = Ver.ParentPkg().Group();
1161 // we don't check for version here as we are better of with upgrading than remove and install
1162 for (Pkg = Grp.PackageList(); Pkg.end() == false; Pkg = Grp.NextPkg(Pkg))
1163 if (Pkg.CurrentVer().end() == false)
1164 break;
1165 if (Pkg.end() == true)
1166 Pkg = Grp.FindPreferredPkg(true);
1167 }
1168 else if (strcmp(D->Package.c_str() + colon, ":native") == 0)
1169 Pkg = Ver.ParentPkg().Group().FindPkg("native");
1170 }
1171
1172 if (forbidden.empty() == false)
1173 {
1174 if (_config->FindB("Debug::BuildDeps",false) == true)
1175 cout << D->Package.substr(colon, string::npos) << " is not allowed from " << forbidden << " package " << (*D).Package << " (" << Ver.VerStr() << ")" << endl;
1176 continue;
1177 }
1178
1179 //we found a good version
1180 break;
1181 }
1182 if (Ver == verlist.end())
1183 {
1184 if (_config->FindB("Debug::BuildDeps",false) == true)
1185 cout << " No multiarch info as we have no satisfying installed nor candidate for " << D->Package << " on build or host arch" << endl;
1186
1187 if (forbidden.empty() == false)
1188 {
1189 if (hasAlternatives)
1190 continue;
1191 return _error->Error(_("%s dependency for %s can't be satisfied "
1192 "because %s is not allowed on '%s' packages"),
1193 Last->BuildDepType(D->Type), Src.c_str(),
1194 D->Package.c_str(), forbidden.c_str());
1195 }
1196 }
1197 }
1198 else
1199 Pkg = Cache->FindPkg(D->Package);
1200
1201 if (Pkg.end() == true || (Pkg->VersionList == 0 && Pkg->ProvidesList == 0))
1202 {
1203 if (_config->FindB("Debug::BuildDeps",false) == true)
1204 cout << " (not found)" << (*D).Package << endl;
1205
1206 if (hasAlternatives)
1207 continue;
1208
1209 return _error->Error(_("%s dependency for %s cannot be satisfied "
1210 "because the package %s cannot be found"),
1211 Last->BuildDepType((*D).Type),Src.c_str(),
1212 (*D).Package.c_str());
1213 }
1214
1215 pkgCache::VerIterator IV = (*Cache)[Pkg].InstVerIter(*Cache);
1216 if (IV.end() == false)
1217 {
1218 if (_config->FindB("Debug::BuildDeps",false) == true)
1219 cout << " Is installed\n";
1220
1221 if (D->Version.empty() == true ||
1222 Cache->VS().CheckDep(IV.VerStr(),(*D).Op,(*D).Version.c_str()) == true)
1223 {
1224 skipAlternatives = hasAlternatives;
1225 continue;
1226 }
1227
1228 if (_config->FindB("Debug::BuildDeps",false) == true)
1229 cout << " ...but the installed version doesn't meet the version requirement\n";
1230
1231 if (((*D).Op & pkgCache::Dep::LessEq) == pkgCache::Dep::LessEq)
1232 return _error->Error(_("Failed to satisfy %s dependency for %s: Installed package %s is too new"),
1233 Last->BuildDepType((*D).Type), Src.c_str(), Pkg.FullName(true).c_str());
1234 }
1235
1236 // Only consider virtual packages if there is no versioned dependency
1237 if ((*D).Version.empty() == true)
1238 {
1239 /*
1240 * If this is a virtual package, we need to check the list of
1241 * packages that provide it and see if any of those are
1242 * installed
1243 */
1244 pkgCache::PrvIterator Prv = Pkg.ProvidesList();
1245 for (; Prv.end() != true; ++Prv)
1246 {
1247 if (_config->FindB("Debug::BuildDeps",false) == true)
1248 cout << " Checking provider " << Prv.OwnerPkg().FullName() << endl;
1249
1250 if ((*Cache)[Prv.OwnerPkg()].InstVerIter(*Cache).end() == false)
1251 break;
1252 }
1253
1254 if (Prv.end() == false)
1255 {
1256 if (_config->FindB("Debug::BuildDeps",false) == true)
1257 cout << " Is provided by installed package " << Prv.OwnerPkg().FullName() << endl;
1258 skipAlternatives = hasAlternatives;
1259 continue;
1260 }
1261 }
1262 else // versioned dependency
1263 {
1264 pkgCache::VerIterator CV = (*Cache)[Pkg].CandidateVerIter(*Cache);
1265 if (CV.end() == true ||
1266 Cache->VS().CheckDep(CV.VerStr(),(*D).Op,(*D).Version.c_str()) == false)
1267 {
1268 if (hasAlternatives)
1269 continue;
1270 else if (CV.end() == false)
1271 return _error->Error(_("%s dependency for %s cannot be satisfied "
1272 "because candidate version of package %s "
1273 "can't satisfy version requirements"),
1274 Last->BuildDepType(D->Type), Src.c_str(),
1275 D->Package.c_str());
1276 else
1277 return _error->Error(_("%s dependency for %s cannot be satisfied "
1278 "because package %s has no candidate version"),
1279 Last->BuildDepType(D->Type), Src.c_str(),
1280 D->Package.c_str());
1281 }
1282 }
1283
1284 if (TryToInstallBuildDep(Pkg,Cache,Fix,false,false,false) == true)
1285 {
1286 // We successfully installed something; skip remaining alternatives
1287 skipAlternatives = hasAlternatives;
1288 if(_config->FindB("APT::Get::Build-Dep-Automatic", false) == true)
1289 Cache->MarkAuto(Pkg, true);
1290 continue;
1291 }
1292 else if (hasAlternatives)
1293 {
1294 if (_config->FindB("Debug::BuildDeps",false) == true)
1295 cout << " Unsatisfiable, trying alternatives\n";
1296 continue;
1297 }
1298 else
1299 {
1300 return _error->Error(_("Failed to satisfy %s dependency for %s: %s"),
1301 Last->BuildDepType((*D).Type),
1302 Src.c_str(),
1303 (*D).Package.c_str());
1304 }
1305 }
1306 }
1307
1308 if (Fix.Resolve(true) == false)
1309 _error->Discard();
1310
1311 // Now we check the state of the packages,
1312 if (Cache->BrokenCount() != 0)
1313 {
1314 ShowBroken(cout, Cache, false);
1315 return _error->Error(_("Build-dependencies for %s could not be satisfied."),*I);
1316 }
1317 }
1318
1319 if (InstallPackages(Cache, false, true) == false)
1320 return _error->Error(_("Failed to process build dependencies"));
1321 return true;
1322 }
1323 /*}}}*/
1324 // GetChangelogPath - return a path pointing to a changelog file or dir /*{{{*/
1325 // ---------------------------------------------------------------------
1326 /* This returns a "path" string for the changelog url construction.
1327 * Please note that its not complete, it either needs a "/changelog"
1328 * appended (for the packages.debian.org/changelogs site) or a
1329 * ".changelog" (for third party sites that store the changelog in the
1330 * pool/ next to the deb itself)
1331 * Example return: "pool/main/a/apt/apt_0.8.8ubuntu3"
1332 */
1333 string GetChangelogPath(CacheFile &Cache,
1334 pkgCache::PkgIterator Pkg,
1335 pkgCache::VerIterator Ver)
1336 {
1337 string path;
1338
1339 pkgRecords Recs(Cache);
1340 pkgRecords::Parser &rec=Recs.Lookup(Ver.FileList());
1341 string srcpkg = rec.SourcePkg().empty() ? Pkg.Name() : rec.SourcePkg();
1342 string ver = Ver.VerStr();
1343 // if there is a source version it always wins
1344 if (rec.SourceVer() != "")
1345 ver = rec.SourceVer();
1346 path = flNotFile(rec.FileName());
1347 path += srcpkg + "_" + StripEpoch(ver);
1348 return path;
1349 }
1350 /*}}}*/
1351 // GuessThirdPartyChangelogUri - return url /*{{{*/
1352 // ---------------------------------------------------------------------
1353 /* Contruct a changelog file path for third party sites that do not use
1354 * packages.debian.org/changelogs
1355 * This simply uses the ArchiveURI() of the source pkg and looks for
1356 * a .changelog file there, Example for "mediabuntu":
1357 * apt-get changelog mplayer-doc:
1358 * http://packages.medibuntu.org/pool/non-free/m/mplayer/mplayer_1.0~rc4~try1.dsfg1-1ubuntu1+medibuntu1.changelog
1359 */
1360 bool GuessThirdPartyChangelogUri(CacheFile &Cache,
1361 pkgCache::PkgIterator Pkg,
1362 pkgCache::VerIterator Ver,
1363 string &out_uri)
1364 {
1365 // get the binary deb server path
1366 pkgCache::VerFileIterator Vf = Ver.FileList();
1367 if (Vf.end() == true)
1368 return false;
1369 pkgCache::PkgFileIterator F = Vf.File();
1370 pkgIndexFile *index;
1371 pkgSourceList *SrcList = Cache.GetSourceList();
1372 if(SrcList->FindIndex(F, index) == false)
1373 return false;
1374
1375 // get archive uri for the binary deb
1376 string path_without_dot_changelog = GetChangelogPath(Cache, Pkg, Ver);
1377 out_uri = index->ArchiveURI(path_without_dot_changelog + ".changelog");
1378
1379 // now strip away the filename and add srcpkg_srcver.changelog
1380 return true;
1381 }
1382 /*}}}*/
1383 // DownloadChangelog - Download the changelog /*{{{*/
1384 // ---------------------------------------------------------------------
1385 bool DownloadChangelog(CacheFile &CacheFile, pkgAcquire &Fetcher,
1386 pkgCache::VerIterator Ver, string targetfile)
1387 /* Download a changelog file for the given package version to
1388 * targetfile. This will first try the server from Apt::Changelogs::Server
1389 * (http://packages.debian.org/changelogs by default) and if that gives
1390 * a 404 tries to get it from the archive directly (see
1391 * GuessThirdPartyChangelogUri for details how)
1392 */
1393 {
1394 string path;
1395 string descr;
1396 string server;
1397 string changelog_uri;
1398
1399 // data structures we need
1400 pkgCache::PkgIterator Pkg = Ver.ParentPkg();
1401
1402 // make the server root configurable
1403 server = _config->Find("Apt::Changelogs::Server",
1404 "http://packages.debian.org/changelogs");
1405 path = GetChangelogPath(CacheFile, Pkg, Ver);
1406 strprintf(changelog_uri, "%s/%s/changelog", server.c_str(), path.c_str());
1407 if (_config->FindB("APT::Get::Print-URIs", false) == true)
1408 {
1409 std::cout << '\'' << changelog_uri << '\'' << std::endl;
1410 return true;
1411 }
1412
1413 strprintf(descr, _("Changelog for %s (%s)"), Pkg.Name(), changelog_uri.c_str());
1414 // queue it
1415 new pkgAcqFile(&Fetcher, changelog_uri, "", 0, descr, Pkg.Name(), "ignored", targetfile);
1416
1417 // try downloading it, if that fails, try third-party-changelogs location
1418 // FIXME: Fetcher.Run() is "Continue" even if I get a 404?!?
1419 Fetcher.Run();
1420 if (!FileExists(targetfile))
1421 {
1422 string third_party_uri;
1423 if (GuessThirdPartyChangelogUri(CacheFile, Pkg, Ver, third_party_uri))
1424 {
1425 strprintf(descr, _("Changelog for %s (%s)"), Pkg.Name(), third_party_uri.c_str());
1426 new pkgAcqFile(&Fetcher, third_party_uri, "", 0, descr, Pkg.Name(), "ignored", targetfile);
1427 Fetcher.Run();
1428 }
1429 }
1430
1431 if (FileExists(targetfile))
1432 return true;
1433
1434 // error
1435 return _error->Error("changelog download failed");
1436 }
1437 /*}}}*/
1438 // DoChangelog - Get changelog from the command line /*{{{*/
1439 // ---------------------------------------------------------------------
1440 bool DoChangelog(CommandLine &CmdL)
1441 {
1442 CacheFile Cache;
1443 if (Cache.ReadOnlyOpen() == false)
1444 return false;
1445
1446 APT::CacheSetHelper helper(c0out);
1447 APT::VersionList verset = APT::VersionList::FromCommandLine(Cache,
1448 CmdL.FileList + 1, APT::VersionList::CANDIDATE, helper);
1449 if (verset.empty() == true)
1450 return false;
1451 pkgAcquire Fetcher;
1452
1453 if (_config->FindB("APT::Get::Print-URIs", false) == true)
1454 {
1455 bool Success = true;
1456 for (APT::VersionList::const_iterator Ver = verset.begin();
1457 Ver != verset.end(); ++Ver)
1458 Success &= DownloadChangelog(Cache, Fetcher, Ver, "");
1459 return Success;
1460 }
1461
1462 AcqTextStatus Stat(ScreenWidth, _config->FindI("quiet",0));
1463 Fetcher.Setup(&Stat);
1464
1465 bool const downOnly = _config->FindB("APT::Get::Download-Only", false);
1466
1467 char tmpname[100];
1468 char* tmpdir = NULL;
1469 if (downOnly == false)
1470 {
1471 const char* const tmpDir = getenv("TMPDIR");
1472 if (tmpDir != NULL && *tmpDir != '\0')
1473 snprintf(tmpname, sizeof(tmpname), "%s/apt-changelog-XXXXXX", tmpDir);
1474 else
1475 strncpy(tmpname, "/tmp/apt-changelog-XXXXXX", sizeof(tmpname));
1476 tmpdir = mkdtemp(tmpname);
1477 if (tmpdir == NULL)
1478 return _error->Errno("mkdtemp", "mkdtemp failed");
1479 }
1480
1481 for (APT::VersionList::const_iterator Ver = verset.begin();
1482 Ver != verset.end();
1483 ++Ver)
1484 {
1485 string changelogfile;
1486 if (downOnly == false)
1487 changelogfile.append(tmpname).append("changelog");
1488 else
1489 changelogfile.append(Ver.ParentPkg().Name()).append(".changelog");
1490 if (DownloadChangelog(Cache, Fetcher, Ver, changelogfile) && downOnly == false)
1491 {
1492 DisplayFileInPager(changelogfile);
1493 // cleanup temp file
1494 unlink(changelogfile.c_str());
1495 }
1496 }
1497 // clenaup tmp dir
1498 if (tmpdir != NULL)
1499 rmdir(tmpdir);
1500 return true;
1501 }
1502 /*}}}*/
1503 // ShowHelp - Show a help screen /*{{{*/
1504 // ---------------------------------------------------------------------
1505 /* */
1506 bool ShowHelp(CommandLine &CmdL)
1507 {
1508 ioprintf(cout,_("%s %s for %s compiled on %s %s\n"),PACKAGE,PACKAGE_VERSION,
1509 COMMON_ARCH,__DATE__,__TIME__);
1510
1511 if (_config->FindB("version") == true)
1512 {
1513 cout << _("Supported modules:") << endl;
1514
1515 for (unsigned I = 0; I != pkgVersioningSystem::GlobalListLen; I++)
1516 {
1517 pkgVersioningSystem *VS = pkgVersioningSystem::GlobalList[I];
1518 if (_system != 0 && _system->VS == VS)
1519 cout << '*';
1520 else
1521 cout << ' ';
1522 cout << "Ver: " << VS->Label << endl;
1523
1524 /* Print out all the packaging systems that will work with
1525 this VS */
1526 for (unsigned J = 0; J != pkgSystem::GlobalListLen; J++)
1527 {
1528 pkgSystem *Sys = pkgSystem::GlobalList[J];
1529 if (_system == Sys)
1530 cout << '*';
1531 else
1532 cout << ' ';
1533 if (Sys->VS->TestCompatibility(*VS) == true)
1534 cout << "Pkg: " << Sys->Label << " (Priority " << Sys->Score(*_config) << ")" << endl;
1535 }
1536 }
1537
1538 for (unsigned I = 0; I != pkgSourceList::Type::GlobalListLen; I++)
1539 {
1540 pkgSourceList::Type *Type = pkgSourceList::Type::GlobalList[I];
1541 cout << " S.L: '" << Type->Name << "' " << Type->Label << endl;
1542 }
1543
1544 for (unsigned I = 0; I != pkgIndexFile::Type::GlobalListLen; I++)
1545 {
1546 pkgIndexFile::Type *Type = pkgIndexFile::Type::GlobalList[I];
1547 cout << " Idx: " << Type->Label << endl;
1548 }
1549
1550 return true;
1551 }
1552
1553 cout <<
1554 _("Usage: apt-get [options] command\n"
1555 " apt-get [options] install|remove pkg1 [pkg2 ...]\n"
1556 " apt-get [options] source pkg1 [pkg2 ...]\n"
1557 "\n"
1558 "apt-get is a simple command line interface for downloading and\n"
1559 "installing packages. The most frequently used commands are update\n"
1560 "and install.\n"
1561 "\n"
1562 "Commands:\n"
1563 " update - Retrieve new lists of packages\n"
1564 " upgrade - Perform an upgrade\n"
1565 " install - Install new packages (pkg is libc6 not libc6.deb)\n"
1566 " remove - Remove packages\n"
1567 " autoremove - Remove automatically all unused packages\n"
1568 " purge - Remove packages and config files\n"
1569 " source - Download source archives\n"
1570 " build-dep - Configure build-dependencies for source packages\n"
1571 " dist-upgrade - Distribution upgrade, see apt-get(8)\n"
1572 " dselect-upgrade - Follow dselect selections\n"
1573 " clean - Erase downloaded archive files\n"
1574 " autoclean - Erase old downloaded archive files\n"
1575 " check - Verify that there are no broken dependencies\n"
1576 " changelog - Download and display the changelog for the given package\n"
1577 " download - Download the binary package into the current directory\n"
1578 "\n"
1579 "Options:\n"
1580 " -h This help text.\n"
1581 " -q Loggable output - no progress indicator\n"
1582 " -qq No output except for errors\n"
1583 " -d Download only - do NOT install or unpack archives\n"
1584 " -s No-act. Perform ordering simulation\n"
1585 " -y Assume Yes to all queries and do not prompt\n"
1586 " -f Attempt to correct a system with broken dependencies in place\n"
1587 " -m Attempt to continue if archives are unlocatable\n"
1588 " -u Show a list of upgraded packages as well\n"
1589 " -b Build the source package after fetching it\n"
1590 " -V Show verbose version numbers\n"
1591 " -c=? Read this configuration file\n"
1592 " -o=? Set an arbitrary configuration option, eg -o dir::cache=/tmp\n"
1593 "See the apt-get(8), sources.list(5) and apt.conf(5) manual\n"
1594 "pages for more information and options.\n"
1595 " This APT has Super Cow Powers.\n");
1596 return true;
1597 }
1598 /*}}}*/
1599 // SigWinch - Window size change signal handler /*{{{*/
1600 // ---------------------------------------------------------------------
1601 /* */
1602 void SigWinch(int)
1603 {
1604 // Riped from GNU ls
1605 #ifdef TIOCGWINSZ
1606 struct winsize ws;
1607
1608 if (ioctl(1, TIOCGWINSZ, &ws) != -1 && ws.ws_col >= 5)
1609 ScreenWidth = ws.ws_col - 1;
1610 #endif
1611 }
1612 /*}}}*/
1613 bool DoUpgrade(CommandLine &CmdL) /*{{{*/
1614 {
1615 if (_config->FindB("APT::Get::Upgrade-Allow-New", false) == true)
1616 return DoUpgradeWithAllowNewPackages(CmdL);
1617 else
1618 return DoUpgradeNoNewPackages(CmdL);
1619 }
1620 /*}}}*/
1621 int main(int argc,const char *argv[]) /*{{{*/
1622 {
1623 CommandLine::Dispatch Cmds[] = {{"update",&DoUpdate},
1624 {"upgrade",&DoUpgrade},
1625 {"install",&DoInstall},
1626 {"remove",&DoInstall},
1627 {"purge",&DoInstall},
1628 {"autoremove",&DoInstall},
1629 {"markauto",&DoMarkAuto},
1630 {"unmarkauto",&DoMarkAuto},
1631 {"dist-upgrade",&DoDistUpgrade},
1632 {"dselect-upgrade",&DoDSelectUpgrade},
1633 {"build-dep",&DoBuildDep},
1634 {"clean",&DoClean},
1635 {"autoclean",&DoAutoClean},
1636 {"check",&DoCheck},
1637 {"source",&DoSource},
1638 {"download",&DoDownload},
1639 {"changelog",&DoChangelog},
1640 {"moo",&DoMoo},
1641 {"help",&ShowHelp},
1642 {0,0}};
1643
1644 std::vector<CommandLine::Args> Args = getCommandArgs("apt-get", CommandLine::GetCommand(Cmds, argc, argv));
1645
1646 // Set up gettext support
1647 setlocale(LC_ALL,"");
1648 textdomain(PACKAGE);
1649
1650 // Parse the command line and initialize the package library
1651 CommandLine CmdL(Args.data(),_config);
1652 if (pkgInitConfig(*_config) == false ||
1653 CmdL.Parse(argc,argv) == false ||
1654 pkgInitSystem(*_config,_system) == false)
1655 {
1656 if (_config->FindB("version") == true)
1657 ShowHelp(CmdL);
1658
1659 _error->DumpErrors();
1660 return 100;
1661 }
1662
1663 // See if the help should be shown
1664 if (_config->FindB("help") == true ||
1665 _config->FindB("version") == true ||
1666 CmdL.FileSize() == 0)
1667 {
1668 ShowHelp(CmdL);
1669 return 0;
1670 }
1671
1672 // see if we are in simulate mode
1673 CheckSimulateMode(CmdL);
1674
1675 // Deal with stdout not being a tty
1676 if (!isatty(STDOUT_FILENO) && _config->FindI("quiet", -1) == -1)
1677 _config->Set("quiet","1");
1678
1679 // Setup the output streams
1680 InitOutput();
1681
1682 // Setup the signals
1683 signal(SIGPIPE,SIG_IGN);
1684 signal(SIGWINCH,SigWinch);
1685 SigWinch(0);
1686
1687 // Match the operation
1688 CmdL.DispatchArg(Cmds);
1689
1690 // Print any errors or warnings found during parsing
1691 bool const Errors = _error->PendingError();
1692 if (_config->FindI("quiet",0) > 0)
1693 _error->DumpErrors();
1694 else
1695 _error->DumpErrors(GlobalError::DEBUG);
1696 return Errors == true ? 100 : 0;
1697 }
1698 /*}}}*/