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