1 // -*- mode: cpp; mode: fold -*-
3 // $Id: apt-get.cc,v 1.156 2004/08/28 01:05:16 mdz Exp $
4 /* ######################################################################
6 apt-get - Cover for dpkg
8 This is an allout cover for dpkg implementing a safer front end. It is
9 based largely on libapt-pkg.
11 The syntax is different,
12 apt-get [opt] command [things]
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 - Powerful upgrader designed to handle the issues with
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
25 ##################################################################### */
27 // Include Files /*{{{*/
30 #include <apt-pkg/acquire-item.h>
31 #include <apt-pkg/algorithms.h>
32 #include <apt-pkg/aptconfiguration.h>
33 #include <apt-pkg/cachefile.h>
34 #include <apt-pkg/cacheset.h>
35 #include <apt-pkg/clean.h>
36 #include <apt-pkg/cmndline.h>
37 #include <apt-pkg/debmetaindex.h>
38 #include <apt-pkg/depcache.h>
39 #include <apt-pkg/error.h>
40 #include <apt-pkg/fileutl.h>
41 #include <apt-pkg/indexfile.h>
42 #include <apt-pkg/init.h>
43 #include <apt-pkg/md5.h>
44 #include <apt-pkg/metaindex.h>
45 #include <apt-pkg/pkgrecords.h>
46 #include <apt-pkg/pkgsystem.h>
47 #include <apt-pkg/progress.h>
48 #include <apt-pkg/sourcelist.h>
49 #include <apt-pkg/srcrecords.h>
50 #include <apt-pkg/strutl.h>
51 #include <apt-pkg/version.h>
52 #include <apt-pkg/acquire.h>
53 #include <apt-pkg/configuration.h>
54 #include <apt-pkg/macros.h>
55 #include <apt-pkg/pkgcache.h>
56 #include <apt-pkg/cacheiterators.h>
57 #include <apt-pkg/upgrade.h>
58 #include <apt-pkg/sptr.h>
60 #include <apt-private/acqprogress.h>
61 #include <apt-private/private-cacheset.h>
62 #include <apt-private/private-cachefile.h>
63 #include <apt-private/private-cmndline.h>
64 #include <apt-private/private-download.h>
65 #include <apt-private/private-install.h>
66 #include <apt-private/private-main.h>
67 #include <apt-private/private-moo.h>
68 #include <apt-private/private-output.h>
69 #include <apt-private/private-update.h>
70 #include <apt-private/private-upgrade.h>
71 #include <apt-private/private-utils.h>
72 #include <apt-private/private-source.h>
80 #include <sys/ioctl.h>
99 /* mark packages as automatically/manually installed. {{{*/
100 static bool DoMarkAuto(CommandLine
&CmdL
)
103 int AutoMarkChanged
= 0;
104 OpTextProgress progress
;
106 if (Cache
.Open() == false)
109 if (strcasecmp(CmdL
.FileList
[0],"markauto") == 0)
111 else if (strcasecmp(CmdL
.FileList
[0],"unmarkauto") == 0)
114 for (const char **I
= CmdL
.FileList
+ 1; *I
!= 0; I
++)
117 // Locate the package
118 pkgCache::PkgIterator Pkg
= Cache
->FindPkg(S
);
119 if (Pkg
.end() == true) {
120 return _error
->Error(_("Couldn't find package %s"),S
);
125 ioprintf(c1out
,_("%s set to manually installed.\n"), Pkg
.Name());
127 ioprintf(c1out
,_("%s set to automatically installed.\n"),
130 Cache
->MarkAuto(Pkg
,Action
);
135 _error
->Notice(_("This command is deprecated. Please use 'apt-mark auto' and 'apt-mark manual' instead."));
137 if (AutoMarkChanged
&& ! _config
->FindB("APT::Get::Simulate",false))
138 return Cache
->writeStateFile(NULL
);
142 // DoDSelectUpgrade - Do an upgrade by following dselects selections /*{{{*/
143 // ---------------------------------------------------------------------
144 /* Follows dselect's selections */
145 static bool DoDSelectUpgrade(CommandLine
&)
148 if (Cache
.OpenForInstall() == false || Cache
.CheckDeps() == false)
151 pkgDepCache::ActionGroup
group(Cache
);
153 // Install everything with the install flag set
154 pkgCache::PkgIterator I
= Cache
->PkgBegin();
155 for (;I
.end() != true; ++I
)
157 /* Install the package only if it is a new install, the autoupgrader
158 will deal with the rest */
159 if (I
->SelectedState
== pkgCache::State::Install
)
160 Cache
->MarkInstall(I
,false);
163 /* Now install their deps too, if we do this above then order of
164 the status file is significant for | groups */
165 for (I
= Cache
->PkgBegin();I
.end() != true; ++I
)
167 /* Install the package only if it is a new install, the autoupgrader
168 will deal with the rest */
169 if (I
->SelectedState
== pkgCache::State::Install
)
170 Cache
->MarkInstall(I
,true);
173 // Apply erasures now, they override everything else.
174 for (I
= Cache
->PkgBegin();I
.end() != true; ++I
)
177 if (I
->SelectedState
== pkgCache::State::DeInstall
||
178 I
->SelectedState
== pkgCache::State::Purge
)
179 Cache
->MarkDelete(I
,I
->SelectedState
== pkgCache::State::Purge
);
182 /* Resolve any problems that dselect created, allupgrade cannot handle
183 such things. We do so quite aggressively too.. */
184 if (Cache
->BrokenCount() != 0)
186 pkgProblemResolver
Fix(Cache
);
188 // Hold back held packages.
189 if (_config
->FindB("APT::Ignore-Hold",false) == false)
191 for (pkgCache::PkgIterator I
= Cache
->PkgBegin(); I
.end() == false; ++I
)
193 if (I
->SelectedState
== pkgCache::State::Hold
)
201 if (Fix
.Resolve() == false)
203 ShowBroken(c1out
,Cache
,false);
204 return _error
->Error(_("Internal error, problem resolver broke stuff"));
208 // Now upgrade everything
209 if (APT::Upgrade::Upgrade(Cache
, APT::Upgrade::FORBID_REMOVE_PACKAGES
| APT::Upgrade::FORBID_INSTALL_NEW_PACKAGES
) == false)
211 ShowBroken(c1out
,Cache
,false);
212 return _error
->Error(_("Internal error, problem resolver broke stuff"));
215 return InstallPackages(Cache
,false);
218 // DoCheck - Perform the check operation /*{{{*/
219 // ---------------------------------------------------------------------
220 /* Opening automatically checks the system, this command is mostly used
222 static bool DoCheck(CommandLine
&)
231 // DoIndexTargets - Lists all IndexTargets /*{{{*/
232 static std::string
format_key(std::string key
)
234 // deb822 is case-insensitive, but the human eye prefers candy
235 std::transform(key
.begin(), key
.end(), key
.begin(), ::tolower
);
236 key
[0] = ::toupper(key
[0]);
237 size_t found
= key
.find("_uri");
238 if (found
!= std::string::npos
)
239 key
.replace(found
, 4, "-URI");
240 while ((found
= key
.find('_')) != std::string::npos
)
243 key
[found
+ 1] = ::toupper(key
[found
+ 1]);
247 static bool DoIndexTargets(CommandLine
&CmdL
)
249 pkgCacheFile CacheFile
;
250 pkgSourceList
*SrcList
= CacheFile
.GetSourceList();
251 pkgCache
*Cache
= CacheFile
.GetPkgCache();
253 if (SrcList
== nullptr || Cache
== nullptr)
256 std::string
const Format
= _config
->Find("APT::Get::IndexTargets::Format");
257 bool const ReleaseInfo
= _config
->FindB("APT::Get::IndexTargets::ReleaseInfo", true);
258 bool Filtered
= CmdL
.FileSize() > 1;
259 for (pkgSourceList::const_iterator S
= SrcList
->begin(); S
!= SrcList
->end(); ++S
)
261 std::vector
<IndexTarget
> const targets
= (*S
)->GetIndexTargets();
262 std::map
<std::string
, string
> AddOptions
;
265 AddOptions
.insert(std::make_pair("TRUSTED", ((*S
)->IsTrusted() ? "yes" : "no")));
266 pkgCache::RlsFileIterator
const RlsFile
= (*S
)->FindInCache(*Cache
, false);
269 #define APT_RELEASE(X,Y) if (RlsFile.Y() != NULL) AddOptions.insert(std::make_pair(X, RlsFile.Y()))
270 APT_RELEASE("CODENAME", Codename
);
271 APT_RELEASE("SUITE", Archive
);
272 APT_RELEASE("VERSION", Version
);
273 APT_RELEASE("ORIGIN", Origin
);
274 APT_RELEASE("LABEL", Label
);
278 for (std::vector
<IndexTarget
>::const_iterator T
= targets
.begin(); T
!= targets
.end(); ++T
)
280 std::string filename
= T
->Option(ReleaseInfo
? IndexTarget::EXISTING_FILENAME
: IndexTarget::FILENAME
);
281 if (filename
.empty())
284 std::ostringstream stanza
;
285 if (Filtered
|| Format
.empty())
287 stanza
<< "MetaKey: " << T
->MetaKey
<< "\n"
288 << "ShortDesc: " << T
->ShortDesc
<< "\n"
289 << "Description: " << T
->Description
<< "\n"
290 << "URI: " << T
->URI
<< "\n"
291 << "Filename: " << filename
<< "\n"
292 << "Optional: " << (T
->IsOptional
? "yes" : "no") << "\n"
293 << "KeepCompressed: " << (T
->KeepCompressed
? "yes" : "no") << "\n";
294 for (std::map
<std::string
,std::string
>::const_iterator O
= AddOptions
.begin(); O
!= AddOptions
.end(); ++O
)
295 stanza
<< format_key(O
->first
) << ": " << O
->second
<< "\n";
296 for (std::map
<std::string
,std::string
>::const_iterator O
= T
->Options
.begin(); O
!= T
->Options
.end(); ++O
)
298 if (O
->first
== "PDIFFS")
299 stanza
<< "PDiffs: " << O
->second
<< "\n";
300 else if (O
->first
== "COMPRESSIONTYPES")
301 stanza
<< "CompressionTypes: " << O
->second
<< "\n";
302 else if (O
->first
== "KEEPCOMPRESSEDAS")
303 stanza
<< "KeepCompressedAs: " << O
->second
<< "\n";
304 else if (O
->first
== "DEFAULTENABLED")
305 stanza
<< "DefaultEnabled: " << O
->second
<< "\n";
307 stanza
<< format_key(O
->first
) << ": " << O
->second
<< "\n";
313 // that is a bit crude, but good enough for now
315 std::string haystack
= std::string("\n") + stanza
.str() + "\n";
316 std::transform(haystack
.begin(), haystack
.end(), haystack
.begin(), ::tolower
);
317 size_t const filesize
= CmdL
.FileSize() - 1;
318 for (size_t i
= 0; i
!= filesize
; ++i
)
320 std::string needle
= std::string("\n") + CmdL
.FileList
[i
+ 1] + "\n";
321 std::transform(needle
.begin(), needle
.end(), needle
.begin(), ::tolower
);
322 if (haystack
.find(needle
) != std::string::npos
)
333 cout
<< stanza
.str();
336 std::string out
= SubstVar(Format
, "$(FILENAME)", filename
);
337 out
= T
->Format(out
);
338 for (std::map
<std::string
,std::string
>::const_iterator O
= AddOptions
.begin(); O
!= AddOptions
.end(); ++O
)
339 out
= SubstVar(out
, std::string("$(") + O
->first
+ ")", O
->second
);
340 cout
<< out
<< std::endl
;
348 static bool ShowHelp(CommandLine
&) /*{{{*/
350 if (_config
->FindB("version") == true)
352 cout
<< _("Supported modules:") << endl
;
354 for (unsigned I
= 0; I
!= pkgVersioningSystem::GlobalListLen
; I
++)
356 pkgVersioningSystem
*VS
= pkgVersioningSystem::GlobalList
[I
];
357 if (_system
!= 0 && _system
->VS
== VS
)
361 cout
<< "Ver: " << VS
->Label
<< endl
;
363 /* Print out all the packaging systems that will work with
365 for (unsigned J
= 0; J
!= pkgSystem::GlobalListLen
; J
++)
367 pkgSystem
*Sys
= pkgSystem::GlobalList
[J
];
372 if (Sys
->VS
->TestCompatibility(*VS
) == true)
373 cout
<< "Pkg: " << Sys
->Label
<< " (Priority " << Sys
->Score(*_config
) << ")" << endl
;
377 for (unsigned I
= 0; I
!= pkgSourceList::Type::GlobalListLen
; I
++)
379 pkgSourceList::Type
*Type
= pkgSourceList::Type::GlobalList
[I
];
380 cout
<< " S.L: '" << Type
->Name
<< "' " << Type
->Label
<< endl
;
383 for (unsigned I
= 0; I
!= pkgIndexFile::Type::GlobalListLen
; I
++)
385 pkgIndexFile::Type
*Type
= pkgIndexFile::Type::GlobalList
[I
];
386 cout
<< " Idx: " << Type
->Label
<< endl
;
393 _("Usage: apt-get [options] command\n"
394 " apt-get [options] install|remove pkg1 [pkg2 ...]\n"
395 " apt-get [options] source pkg1 [pkg2 ...]\n"
397 "apt-get is a command line interface for retrieval of packages\n"
398 "and information about them from authenticated sources and\n"
399 "for installation, upgrade and removal of packages together\n"
400 "with their dependencies.\n");
404 static std::vector
<aptDispatchWithHelp
> GetCommands() /*{{{*/
407 {"update", &DoUpdate
, _("Retrieve new lists of packages")},
408 {"upgrade", &DoUpgrade
, _("Perform an upgrade")},
409 {"install", &DoInstall
, _("Install new packages (pkg is libc6 not libc6.deb)")},
410 {"remove", &DoInstall
, _("Remove packages")},
411 {"purge", &DoInstall
, _("Remove packages and config files")},
412 {"autoremove", &DoInstall
, _("Remove automatically all unused packages")},
413 {"auto-remove", &DoInstall
, nullptr},
414 {"markauto", &DoMarkAuto
, nullptr},
415 {"unmarkauto", &DoMarkAuto
, nullptr},
416 {"dist-upgrade", &DoDistUpgrade
, _("Distribution upgrade, see apt-get(8)")},
417 {"full-upgrade", &DoDistUpgrade
, nullptr},
418 {"dselect-upgrade", &DoDSelectUpgrade
, _("Follow dselect selections")},
419 {"build-dep", &DoBuildDep
, _("Configure build-dependencies for source packages")},
420 {"clean", &DoClean
, _("Erase downloaded archive files")},
421 {"autoclean", &DoAutoClean
, _("Erase old downloaded archive files")},
422 {"auto-clean", &DoAutoClean
, nullptr},
423 {"check", &DoCheck
, _("Verify that there are no broken dependencies")},
424 {"source", &DoSource
, _("Download source archives")},
425 {"download", &DoDownload
, _("Download the binary package into the current directory")},
426 {"changelog", &DoChangelog
, _("Download and display the changelog for the given package")},
427 {"indextargets", &DoIndexTargets
, nullptr},
428 {"moo", &DoMoo
, nullptr},
429 {nullptr, nullptr, nullptr}
433 int main(int argc
,const char *argv
[]) /*{{{*/
435 // Parse the command line and initialize the package library
437 auto const Cmds
= ParseCommandLine(CmdL
, APT_CMD::APT_GET
, &_config
, &_system
, argc
, argv
, &ShowHelp
, &GetCommands
);
442 CheckIfSimulateMode(CmdL
);
444 return DispatchCommandLine(CmdL
, Cmds
);