apt-extracttemplates cleanup
[ntk/apt.git] / cmdline / apt-extracttemplates.cc
CommitLineData
234edfd0
AL
1// -*- mode: cpp; mode: fold -*-
2// Description /*{{{*/
3// $Id: apt-extracttemplates.cc,v 1.2 2001/02/25 04:53:59 tausq Exp $
4/* ######################################################################
5
6 APT Extract Templates - Program to extract debconf config and template
7 files
3fc8f685 8
234edfd0
AL
9 This is a simple program to extract config and template information
10 from Debian packages. It can be used to speed up the preconfiguration
11 process for debconf-enabled packages
12
13 ##################################################################### */
14 /*}}}*/
15// Include Files /*{{{*/
3fc8f685
AL
16#include <apt-pkg/init.h>
17#if APT_PKG_MAJOR >= 3
18#define APT_COMPATIBILITY 986
19#include <apt-pkg/debversion.h>
20#endif
21#include <apt-pkg/pkgcache.h>
22#include <apt-pkg/configuration.h>
23#include <apt-pkg/progress.h>
24#include <apt-pkg/sourcelist.h>
25#include <apt-pkg/pkgcachegen.h>
26#include <apt-pkg/version.h>
234edfd0
AL
27#include <apt-pkg/tagfile.h>
28#include <apt-pkg/extracttar.h>
29#include <apt-pkg/arfile.h>
30#include <apt-pkg/deblistparser.h>
31#include <apt-pkg/error.h>
32#include <apt-pkg/strutl.h>
3fc8f685 33
234edfd0
AL
34#include <stdio.h>
35#include <string.h>
36#include <stdlib.h>
37#include <unistd.h>
38#define _GNU_SOURCE
39#include <getopt.h>
40#include <wait.h>
41#include <fstream.h>
42
43#include <config.h>
44#include <apti18n.h>
45#include "apt-extracttemplates.h"
46
47#define TMPDIR "/var/lib/debconf/"
3fc8f685 48
234edfd0
AL
49pkgCache *DebFile::Cache = 0;
50
51// DebFile::DebFile - Construct the DebFile object /*{{{*/
52// ---------------------------------------------------------------------
53/* */
54DebFile::DebFile(const char *debfile)
55 : File(debfile, FileFd::ReadOnly), Control(0), DepOp(0), PreDepOp(0),
56 Config(0), Template(0), Which(None)
3fc8f685 57{
3fc8f685 58}
234edfd0
AL
59 /*}}}*/
60// DebFile::~DebFile - Destruct the DebFile object /*{{{*/
61// ---------------------------------------------------------------------
62/* */
63DebFile::~DebFile()
64{
65 delete [] Control;
66 delete [] Config;
67 delete [] Template;
68}
69 /*}}}*/
70// DebFile::GetInstalledVer - Find out the installed version of a pkg /*{{{*/
71// ---------------------------------------------------------------------
72/* */
73char *DebFile::GetInstalledVer(const string &package)
74{
75 char *ver = 0;
76
77 pkgCache::PkgIterator Pkg = Cache->FindPkg(package);
78 if (Pkg.end() == false)
79 {
80 pkgCache::VerIterator V = Pkg.CurrentVer();
81 if (V.end() == false)
82 {
83 ver = strdup(V.VerStr());
84 }
85 }
3fc8f685 86
234edfd0
AL
87 return ver;
88}
89 /*}}}*/
90// DebFile::Go - Start extracting a debian package /*{{{*/
91// ---------------------------------------------------------------------
92/* */
93bool DebFile::Go()
94{
95 ARArchive AR(File);
96 const ARArchive::Member *Member = AR.FindMember("control.tar.gz");
97 if (Member == 0)
98 {
99 fprintf(stderr, _("This is not a valid DEB package.\n"));
100 return false;
101 }
102
103 if (File.Seek(Member->Start) == false)
104 {
105 return false;
106 }
107
108 ExtractTar Tar(File, Member->Size);
109 return Tar.Go(*this);
110}
111 /*}}}*/
112// DebFile::DoItem examine element in package and mark /*{{{*/
113// ---------------------------------------------------------------------
114/* */
115bool DebFile::DoItem(Item &I, int &Fd)
116{
117 if (strcmp(I.Name, "control") == 0)
118 {
119 delete [] Control;
120 Control = new char[I.Size+1];
121 Control[I.Size] = 0;
122 Which = IsControl;
123 ControlLen = I.Size;
124 // make it call the Process method below. this is so evil
125 Fd = -2;
126 }
127 else if (strcmp(I.Name, "config") == 0)
128 {
129 delete [] Config;
130 Config = new char[I.Size+1];
131 Config[I.Size] = 0;
132 Which = IsConfig;
133 Fd = -2;
134 }
135 else if (strcmp(I.Name, "templates") == 0)
136 {
137 delete [] Template;
138 Template = new char[I.Size+1];
139 Template[I.Size] = 0;
140 Which = IsTemplate;
141 Fd = -2;
142 }
143 else
144 {
145 Fd = -1;
146 }
147 return true;
148}
149 /*}}}*/
150// DebFile::Process examine element in package and copy /*{{{*/
151// ---------------------------------------------------------------------
152/* */
153bool DebFile::Process(Item &I, const unsigned char *data,
154 unsigned long size, unsigned long pos)
155{
156 switch (Which)
157 {
158 case IsControl:
159 memcpy(Control + pos, data, size);
160 break;
161 case IsConfig:
162 memcpy(Config + pos, data, size);
163 break;
164 case IsTemplate:
165 memcpy(Template + pos, data, size);
166 break;
167 default: /* throw it away */ ;
168 }
169 return true;
170}
171 /*}}}*/
172// DebFile::ParseInfo - Parse control file for dependency info /*{{{*/
173// ---------------------------------------------------------------------
174/* */
175bool DebFile::ParseInfo()
176{
177 if (Control == NULL) return false;
178 pkgTagSection Section;
179 Section.Scan(Control, ControlLen);
180
181 Package = Section.FindS("Package");
182 Version = GetInstalledVer(Package);
183
184 const char *Start, *Stop;
185 if (Section.Find("Depends", Start, Stop) == true)
186 {
187 while (1)
188 {
189 string P, V;
190 unsigned int Op;
191 Start = debListParser::ParseDepends(Start, Stop, P, V, Op);
192 if (Start == 0) return false;
193 if (P == "debconf")
194 {
195 DepVer = V;
196 DepOp = Op;
197 break;
198 }
199 if (Start == Stop) break;
200 }
201 }
202
203 if (Section.Find("Pre-Depends", Start, Stop) == true)
204 {
205 while (1)
206 {
207 string P, V;
208 unsigned int Op;
209 Start = debListParser::ParseDepends(Start, Stop, P, V, Op);
210 if (Start == 0) return false;
211 if (P == "debconf")
212 {
213 PreDepVer = V;
214 PreDepOp = Op;
215 break;
216 }
217 if (Start == Stop) break;
218 }
219 }
220
221 return true;
222}
223 /*}}}*/
224// ShowHelp - show a short help text /*{{{*/
225// ---------------------------------------------------------------------
226/* */
227void ShowHelp(void)
228{
229 ioprintf(cout,_("%s %s for %s %s compiled on %s %s\n"),PACKAGE,VERSION,
230 COMMON_OS,COMMON_CPU,__DATE__,__TIME__);
231
232 fprintf(stderr,
233 _("Usage: apt-extracttemplates file1 [file2 ...]\n"
234 "\n"
235 "apt-extracttemplates is a tool to extract config and template info\n"
236 "from debian packages\n"));
237 exit(0);
238}
239 /*}}}*/
240// WriteFile - write the contents of the passed string to a file /*{{{*/
241// ---------------------------------------------------------------------
242/* */
243char *WriteFile(const char *prefix, const char *data)
3fc8f685
AL
244{
245 char fn[512];
246 static int i;
247 snprintf(fn, sizeof(fn), "%s%s.%u%d", TMPDIR, prefix, getpid(), i++);
248
3fc8f685
AL
249 ofstream ofs(fn);
250 if (!ofs) return NULL;
234edfd0 251 ofs << (data ? data : "");
3fc8f685
AL
252 ofs.close();
253 return strdup(fn);
254}
234edfd0
AL
255 /*}}}*/
256// WriteConfig - write out the config data from a debian package file /*{{{*/
257// ---------------------------------------------------------------------
258/* */
259void WriteConfig(const DebFile &file)
3fc8f685 260{
234edfd0
AL
261 char *templatefile = WriteFile("template", file.Template);
262 char *configscript = WriteFile("config", file.Config);
3fc8f685
AL
263
264 if (templatefile == 0 || configscript == 0)
265 {
234edfd0 266 fprintf(stderr, _("Cannot write config script or templates\n"));
3fc8f685
AL
267 return;
268 }
234edfd0
AL
269 cout << file.Package << " " << file.Version << " "
270 << templatefile << " " << configscript << endl;
3fc8f685 271
234edfd0
AL
272 free(templatefile);
273 free(configscript);
274}
275 /*}}}*/
276// InitCache - initialize the package cache /*{{{*/
277// ---------------------------------------------------------------------
278/* */
279int InitCache(MMap *&Map, pkgCache *&Cache)
3fc8f685
AL
280{
281 // Initialize the apt cache
282 if (pkgInitConfig(*_config) == false || pkgInitSystem(*_config, _system) == false)
283 {
234edfd0
AL
284 _error->DumpErrors();
285 return -1;
3fc8f685
AL
286 }
287 pkgSourceList List;
288 List.ReadMainList();
289 OpProgress Prog;
290 pkgMakeStatusCache(List,Prog,&Map,true);
291 Cache = new pkgCache(Map);
234edfd0 292 return 0;
3fc8f685 293}
234edfd0 294 /*}}}*/
3fc8f685
AL
295
296int main(int argc, char **argv, char **env)
297{
298 int idx = 0;
299 char **debs = 0;
300 int numdebs = 0;
301 MMap *Map = 0;
302 const char *debconfver = NULL;
303
234edfd0
AL
304 // Initialize the package cache
305 if (InitCache(Map, DebFile::Cache) < 0 || Map == 0 || DebFile::Cache == 0)
3fc8f685 306 {
234edfd0
AL
307 fprintf(stderr, _("Cannot initialize APT cache\n"));
308 return 100;
3fc8f685
AL
309 }
310
234edfd0
AL
311 // Find out what version of debconf is currently installed
312 if ((debconfver = DebFile::GetInstalledVer("debconf")) == NULL)
3fc8f685 313 {
234edfd0 314 fprintf(stderr, _("Cannot get debconf version. Is debconf installed?\n"));
3fc8f685
AL
315 return 1;
316 }
317
234edfd0 318 // Process each package passsed in
3fc8f685
AL
319 numdebs = argc - 1;
320 debs = new char *[numdebs];
321 memcpy(debs, &argv[1], sizeof(char *) * numdebs);
322
234edfd0 323 if (numdebs < 1) ShowHelp();
3fc8f685
AL
324
325 for (idx = 0; idx < numdebs; idx++)
326 {
327 DebFile file(debs[idx]);
328 if (file.Go() == false)
329 {
234edfd0 330 fprintf(stderr, _("Cannot read %s\n"), debs[idx]);
3fc8f685
AL
331 continue;
332 }
234edfd0 333 // Does the package have templates?
3fc8f685
AL
334 if (file.Template != 0 && file.ParseInfo() == true)
335 {
234edfd0
AL
336 // Check to make sure debconf dependencies are
337 // satisfied
338 if (file.DepVer != "" &&
339 pkgCheckDep(file.DepVer.c_str(),
3fc8f685
AL
340 debconfver, file.DepOp) == false)
341 continue;
234edfd0
AL
342 if (file.PreDepVer != "" &&
343 pkgCheckDep(file.PreDepVer.c_str(),
3fc8f685
AL
344 debconfver, file.PreDepOp) == false)
345 continue;
346
234edfd0 347 WriteConfig(file);
3fc8f685
AL
348 }
349 }
350
351
352 delete Map;
353 delete DebFile::Cache;
354
355 return 0;
356}