g++ 4.7 fixes
[ntk/apt.git] / cmdline / apt-mark.cc
1 // -*- mode: cpp; mode: fold -*-
2 // Description /*{{{*/
3 /* #####################################################################
4 apt-mark - show and change auto-installed bit information
5 ##################################################################### */
6 /*}}}*/
7 // Include Files /*{{{*/
8 #include <config.h>
9
10 #include <apt-pkg/cachefile.h>
11 #include <apt-pkg/cacheset.h>
12 #include <apt-pkg/cmndline.h>
13 #include <apt-pkg/error.h>
14 #include <apt-pkg/init.h>
15 #include <apt-pkg/strutl.h>
16 #include <apt-pkg/pkgsystem.h>
17
18 #include <algorithm>
19 #include <unistd.h>
20
21 #include <apti18n.h>
22 /*}}}*/
23 using namespace std;
24
25 ostream c0out(0);
26 ostream c1out(0);
27 ostream c2out(0);
28 ofstream devnull("/dev/null");
29 /* DoAuto - mark packages as automatically/manually installed {{{*/
30 bool DoAuto(CommandLine &CmdL)
31 {
32 pkgCacheFile CacheFile;
33 pkgCache *Cache = CacheFile.GetPkgCache();
34 pkgDepCache *DepCache = CacheFile.GetDepCache();
35 if (unlikely(Cache == NULL || DepCache == NULL))
36 return false;
37
38 APT::PackageSet pkgset = APT::PackageSet::FromCommandLine(CacheFile, CmdL.FileList + 1);
39 if (pkgset.empty() == true)
40 return _error->Error(_("No packages found"));
41
42 bool MarkAuto = strcasecmp(CmdL.FileList[0],"auto") == 0;
43 int AutoMarkChanged = 0;
44
45 for (APT::PackageSet::const_iterator Pkg = pkgset.begin(); Pkg != pkgset.end(); ++Pkg)
46 {
47 if (Pkg->CurrentVer == 0)
48 {
49 ioprintf(c1out,_("%s can not be marked as it is not installed.\n"), Pkg.FullName(true).c_str());
50 continue;
51 }
52 else if ((((*DepCache)[Pkg].Flags & pkgCache::Flag::Auto) == pkgCache::Flag::Auto) == MarkAuto)
53 {
54 if (MarkAuto == false)
55 ioprintf(c1out,_("%s was already set to manually installed.\n"), Pkg.FullName(true).c_str());
56 else
57 ioprintf(c1out,_("%s was already set to automatically installed.\n"), Pkg.FullName(true).c_str());
58 continue;
59 }
60
61 if (MarkAuto == false)
62 ioprintf(c1out,_("%s set to manually installed.\n"), Pkg.FullName(true).c_str());
63 else
64 ioprintf(c1out,_("%s set to automatically installed.\n"), Pkg.FullName(true).c_str());
65
66 DepCache->MarkAuto(Pkg, MarkAuto);
67 ++AutoMarkChanged;
68 }
69 if (AutoMarkChanged > 0 && _config->FindB("APT::Mark::Simulate", false) == false)
70 return DepCache->writeStateFile(NULL);
71 return true;
72 }
73 /*}}}*/
74 /* DoMarkAuto - mark packages as automatically/manually installed {{{*/
75 /* Does the same as DoAuto but tries to do it exactly the same why as
76 the python implementation did it so it can be a drop-in replacement */
77 bool DoMarkAuto(CommandLine &CmdL)
78 {
79 pkgCacheFile CacheFile;
80 pkgCache *Cache = CacheFile.GetPkgCache();
81 pkgDepCache *DepCache = CacheFile.GetDepCache();
82 if (unlikely(Cache == NULL || DepCache == NULL))
83 return false;
84
85 APT::PackageSet pkgset = APT::PackageSet::FromCommandLine(CacheFile, CmdL.FileList + 1);
86 if (pkgset.empty() == true)
87 return _error->Error(_("No packages found"));
88
89 bool const MarkAuto = strcasecmp(CmdL.FileList[0],"markauto") == 0;
90 bool const Verbose = _config->FindB("APT::MarkAuto::Verbose", false);
91 int AutoMarkChanged = 0;
92
93 for (APT::PackageSet::const_iterator Pkg = pkgset.begin(); Pkg != pkgset.end(); ++Pkg)
94 {
95 if (Pkg->CurrentVer == 0 ||
96 (((*DepCache)[Pkg].Flags & pkgCache::Flag::Auto) == pkgCache::Flag::Auto) == MarkAuto)
97 continue;
98
99 if (Verbose == true)
100 ioprintf(c1out, "changing %s to %d\n", Pkg.Name(), (MarkAuto == false) ? 0 : 1);
101
102 DepCache->MarkAuto(Pkg, MarkAuto);
103 ++AutoMarkChanged;
104 }
105 if (AutoMarkChanged > 0 && _config->FindB("APT::Mark::Simulate", false) == false)
106 return DepCache->writeStateFile(NULL);
107
108 _error->Notice(_("This command is deprecated. Please use 'apt-mark auto' and 'apt-mark manual' instead."));
109
110 return true;
111 }
112 /*}}}*/
113 /* ShowAuto - show automatically installed packages (sorted) {{{*/
114 bool ShowAuto(CommandLine &CmdL)
115 {
116 pkgCacheFile CacheFile;
117 pkgCache *Cache = CacheFile.GetPkgCache();
118 pkgDepCache *DepCache = CacheFile.GetDepCache();
119 if (unlikely(Cache == NULL || DepCache == NULL))
120 return false;
121
122 std::vector<string> packages;
123
124 bool const ShowAuto = strcasecmp(CmdL.FileList[0],"showauto") == 0;
125
126 if (CmdL.FileList[1] == 0)
127 {
128 packages.reserve(Cache->HeaderP->PackageCount / 3);
129 for (pkgCache::PkgIterator P = Cache->PkgBegin(); P.end() == false; ++P)
130 if (P->CurrentVer != 0 &&
131 (((*DepCache)[P].Flags & pkgCache::Flag::Auto) == pkgCache::Flag::Auto) == ShowAuto)
132 packages.push_back(P.FullName(true));
133 }
134 else
135 {
136 APT::CacheSetHelper helper(false); // do not show errors
137 APT::PackageSet pkgset = APT::PackageSet::FromCommandLine(CacheFile, CmdL.FileList + 1, helper);
138 packages.reserve(pkgset.size());
139 for (APT::PackageSet::const_iterator P = pkgset.begin(); P != pkgset.end(); ++P)
140 if (P->CurrentVer != 0 &&
141 (((*DepCache)[P].Flags & pkgCache::Flag::Auto) == pkgCache::Flag::Auto) == ShowAuto)
142 packages.push_back(P.FullName(true));
143 }
144
145 std::sort(packages.begin(), packages.end());
146
147 for (vector<string>::const_iterator I = packages.begin(); I != packages.end(); ++I)
148 std::cout << *I << std::endl;
149
150 return true;
151 }
152 /*}}}*/
153 /* DoHold - mark packages as hold by dpkg {{{*/
154 bool DoHold(CommandLine &CmdL)
155 {
156 pkgCacheFile CacheFile;
157 pkgCache *Cache = CacheFile.GetPkgCache();
158 if (unlikely(Cache == NULL))
159 return false;
160
161 APT::PackageSet pkgset = APT::PackageSet::FromCommandLine(CacheFile, CmdL.FileList + 1);
162 if (pkgset.empty() == true)
163 return _error->Error(_("No packages found"));
164
165 bool const MarkHold = strcasecmp(CmdL.FileList[0],"hold") == 0;
166
167 for (APT::PackageSet::iterator Pkg = pkgset.begin(); Pkg != pkgset.end(); ++Pkg)
168 {
169 if ((Pkg->SelectedState == pkgCache::State::Hold) == MarkHold)
170 {
171 if (MarkHold == true)
172 ioprintf(c1out,_("%s was already set on hold.\n"), Pkg.FullName(true).c_str());
173 else
174 ioprintf(c1out,_("%s was already not hold.\n"), Pkg.FullName(true).c_str());
175 pkgset.erase(Pkg);
176 continue;
177 }
178 }
179
180 if (pkgset.empty() == true)
181 return true;
182
183 if (_config->FindB("APT::Mark::Simulate", false) == true)
184 {
185 for (APT::PackageSet::iterator Pkg = pkgset.begin(); Pkg != pkgset.end(); ++Pkg)
186 {
187 if (MarkHold == false)
188 ioprintf(c1out,_("%s set on hold.\n"), Pkg.FullName(true).c_str());
189 else
190 ioprintf(c1out,_("Canceled hold on %s.\n"), Pkg.FullName(true).c_str());
191 }
192 return true;
193 }
194
195 string dpkgcall = _config->Find("Dir::Bin::dpkg", "dpkg");
196 std::vector<string> const dpkgoptions = _config->FindVector("DPkg::options");
197 for (std::vector<string>::const_iterator o = dpkgoptions.begin();
198 o != dpkgoptions.end(); ++o)
199 dpkgcall.append(" ").append(*o);
200 dpkgcall.append(" --set-selections");
201 FILE *dpkg = popen(dpkgcall.c_str(), "w");
202 if (dpkg == NULL)
203 return _error->Errno("DoHold", "fdopen on dpkg stdin failed");
204
205 for (APT::PackageSet::iterator Pkg = pkgset.begin(); Pkg != pkgset.end(); ++Pkg)
206 {
207 if (MarkHold == true)
208 {
209 fprintf(dpkg, "%s hold\n", Pkg.FullName(true).c_str());
210 ioprintf(c1out,_("%s set on hold.\n"), Pkg.FullName(true).c_str());
211 }
212 else
213 {
214 fprintf(dpkg, "%s install\n", Pkg.FullName(true).c_str());
215 ioprintf(c1out,_("Canceled hold on %s.\n"), Pkg.FullName(true).c_str());
216 }
217 }
218
219 int const status = pclose(dpkg);
220 if (status == -1)
221 return _error->Errno("DoHold", "dpkg execution failed in the end");
222 if (WIFEXITED(status) == false || WEXITSTATUS(status) != 0)
223 return _error->Error(_("Executing dpkg failed. Are you root?"));
224 return true;
225 }
226 /*}}}*/
227 /* ShowHold - show packages set on hold in dpkg status {{{*/
228 bool ShowHold(CommandLine &CmdL)
229 {
230 pkgCacheFile CacheFile;
231 pkgCache *Cache = CacheFile.GetPkgCache();
232 if (unlikely(Cache == NULL))
233 return false;
234
235 std::vector<string> packages;
236
237 if (CmdL.FileList[1] == 0)
238 {
239 packages.reserve(50); // how many holds are realistic? I hope just a few…
240 for (pkgCache::PkgIterator P = Cache->PkgBegin(); P.end() == false; ++P)
241 if (P->SelectedState == pkgCache::State::Hold)
242 packages.push_back(P.FullName(true));
243 }
244 else
245 {
246 APT::CacheSetHelper helper(false); // do not show errors
247 APT::PackageSet pkgset = APT::PackageSet::FromCommandLine(CacheFile, CmdL.FileList + 1, helper);
248 packages.reserve(pkgset.size());
249 for (APT::PackageSet::const_iterator P = pkgset.begin(); P != pkgset.end(); ++P)
250 if (P->SelectedState == pkgCache::State::Hold)
251 packages.push_back(P.FullName(true));
252 }
253
254 std::sort(packages.begin(), packages.end());
255
256 for (vector<string>::const_iterator I = packages.begin(); I != packages.end(); ++I)
257 std::cout << *I << std::endl;
258
259 return true;
260 }
261 /*}}}*/
262 // ShowHelp - Show a help screen /*{{{*/
263 // ---------------------------------------------------------------------
264 /* */
265 bool ShowHelp(CommandLine &CmdL)
266 {
267 ioprintf(cout,_("%s %s for %s compiled on %s %s\n"),PACKAGE,VERSION,
268 COMMON_ARCH,__DATE__,__TIME__);
269
270 cout <<
271 _("Usage: apt-mark [options] {auto|manual} pkg1 [pkg2 ...]\n"
272 "\n"
273 "apt-mark is a simple command line interface for marking packages\n"
274 "as manual or automatical installed. It can also list marks.\n"
275 "\n"
276 "Commands:\n"
277 " auto - Mark the given packages as automatically installed\n"
278 " manual - Mark the given packages as manually installed\n"
279 "\n"
280 "Options:\n"
281 " -h This help text.\n"
282 " -q Loggable output - no progress indicator\n"
283 " -qq No output except for errors\n"
284 " -s No-act. Just prints what would be done.\n"
285 " -f read/write auto/manual marking in the given file\n"
286 " -c=? Read this configuration file\n"
287 " -o=? Set an arbitrary configuration option, eg -o dir::cache=/tmp\n"
288 "See the apt-mark(8) and apt.conf(5) manual pages for more information.")
289 << std::endl;
290 return true;
291 }
292 /*}}}*/
293 int main(int argc,const char *argv[]) /*{{{*/
294 {
295 CommandLine::Args Args[] = {
296 {'h',"help","help",0},
297 {0,"version","version",0},
298 {'q',"quiet","quiet",CommandLine::IntLevel},
299 {'q',"silent","quiet",CommandLine::IntLevel},
300 {'v',"verbose","APT::MarkAuto::Verbose",0},
301 {'s',"simulate","APT::Mark::Simulate",0},
302 {'s',"just-print","APT::Mark::Simulate",0},
303 {'s',"recon","APT::Mark::Simulate",0},
304 {'s',"dry-run","APT::Mark::Simulate",0},
305 {'s',"no-act","APT::Mark::Simulate",0},
306 {'f',"file","Dir::State::extended_states",CommandLine::HasArg},
307 {'c',"config-file",0,CommandLine::ConfigFile},
308 {'o',"option",0,CommandLine::ArbItem},
309 {0,0,0,0}};
310 CommandLine::Dispatch Cmds[] = {{"help",&ShowHelp},
311 {"auto",&DoAuto},
312 {"manual",&DoAuto},
313 {"hold",&DoHold},
314 {"unhold",&DoHold},
315 {"showauto",&ShowAuto},
316 {"showmanual",&ShowAuto},
317 {"showhold",&ShowHold},
318 // be nice and forgive the typo
319 {"showholds",&ShowHold},
320 // be nice and forgive it as it is technical right
321 {"install",&DoHold},
322 // obsolete commands for compatibility
323 {"markauto", &DoMarkAuto},
324 {"unmarkauto", &DoMarkAuto},
325 {0,0}};
326
327 // Set up gettext support
328 setlocale(LC_ALL,"");
329 textdomain(PACKAGE);
330
331 // Parse the command line and initialize the package library
332 CommandLine CmdL(Args,_config);
333 if (pkgInitConfig(*_config) == false ||
334 CmdL.Parse(argc,argv) == false ||
335 pkgInitSystem(*_config,_system) == false)
336 {
337 if (_config->FindB("version") == true)
338 ShowHelp(CmdL);
339 _error->DumpErrors();
340 return 100;
341 }
342
343 // See if the help should be shown
344 if (_config->FindB("help") == true ||
345 _config->FindB("version") == true ||
346 CmdL.FileSize() == 0)
347 {
348 ShowHelp(CmdL);
349 return 0;
350 }
351
352 // Deal with stdout not being a tty
353 if (!isatty(STDOUT_FILENO) && _config->FindI("quiet", -1) == -1)
354 _config->Set("quiet","1");
355
356 // Setup the output streams
357 c0out.rdbuf(cout.rdbuf());
358 c1out.rdbuf(cout.rdbuf());
359 c2out.rdbuf(cout.rdbuf());
360 if (_config->FindI("quiet",0) > 0)
361 c0out.rdbuf(devnull.rdbuf());
362 if (_config->FindI("quiet",0) > 1)
363 c1out.rdbuf(devnull.rdbuf());
364
365 // Match the operation
366 CmdL.DispatchArg(Cmds);
367
368 // Print any errors or warnings found during parsing
369 bool const Errors = _error->PendingError();
370 if (_config->FindI("quiet",0) > 0)
371 _error->DumpErrors();
372 else
373 _error->DumpErrors(GlobalError::DEBUG);
374 return Errors == true ? 100 : 0;
375 }
376 /*}}}*/