]> git.saurik.com Git - apt.git/blob - cmdline/apt-extracttemplates.cc
apt-extracttemplates cleanup
[apt.git] / cmdline / apt-extracttemplates.cc
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
8
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 /*{{{*/
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>
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>
33
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/"
48
49 pkgCache *DebFile::Cache = 0;
50
51 // DebFile::DebFile - Construct the DebFile object /*{{{*/
52 // ---------------------------------------------------------------------
53 /* */
54 DebFile::DebFile(const char *debfile)
55 : File(debfile, FileFd::ReadOnly), Control(0), DepOp(0), PreDepOp(0),
56 Config(0), Template(0), Which(None)
57 {
58 }
59 /*}}}*/
60 // DebFile::~DebFile - Destruct the DebFile object /*{{{*/
61 // ---------------------------------------------------------------------
62 /* */
63 DebFile::~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 /* */
73 char *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 }
86
87 return ver;
88 }
89 /*}}}*/
90 // DebFile::Go - Start extracting a debian package /*{{{*/
91 // ---------------------------------------------------------------------
92 /* */
93 bool 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 /* */
115 bool 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 /* */
153 bool 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 /* */
175 bool 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 /* */
227 void 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 /* */
243 char *WriteFile(const char *prefix, const char *data)
244 {
245 char fn[512];
246 static int i;
247 snprintf(fn, sizeof(fn), "%s%s.%u%d", TMPDIR, prefix, getpid(), i++);
248
249 ofstream ofs(fn);
250 if (!ofs) return NULL;
251 ofs << (data ? data : "");
252 ofs.close();
253 return strdup(fn);
254 }
255 /*}}}*/
256 // WriteConfig - write out the config data from a debian package file /*{{{*/
257 // ---------------------------------------------------------------------
258 /* */
259 void WriteConfig(const DebFile &file)
260 {
261 char *templatefile = WriteFile("template", file.Template);
262 char *configscript = WriteFile("config", file.Config);
263
264 if (templatefile == 0 || configscript == 0)
265 {
266 fprintf(stderr, _("Cannot write config script or templates\n"));
267 return;
268 }
269 cout << file.Package << " " << file.Version << " "
270 << templatefile << " " << configscript << endl;
271
272 free(templatefile);
273 free(configscript);
274 }
275 /*}}}*/
276 // InitCache - initialize the package cache /*{{{*/
277 // ---------------------------------------------------------------------
278 /* */
279 int InitCache(MMap *&Map, pkgCache *&Cache)
280 {
281 // Initialize the apt cache
282 if (pkgInitConfig(*_config) == false || pkgInitSystem(*_config, _system) == false)
283 {
284 _error->DumpErrors();
285 return -1;
286 }
287 pkgSourceList List;
288 List.ReadMainList();
289 OpProgress Prog;
290 pkgMakeStatusCache(List,Prog,&Map,true);
291 Cache = new pkgCache(Map);
292 return 0;
293 }
294 /*}}}*/
295
296 int 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
304 // Initialize the package cache
305 if (InitCache(Map, DebFile::Cache) < 0 || Map == 0 || DebFile::Cache == 0)
306 {
307 fprintf(stderr, _("Cannot initialize APT cache\n"));
308 return 100;
309 }
310
311 // Find out what version of debconf is currently installed
312 if ((debconfver = DebFile::GetInstalledVer("debconf")) == NULL)
313 {
314 fprintf(stderr, _("Cannot get debconf version. Is debconf installed?\n"));
315 return 1;
316 }
317
318 // Process each package passsed in
319 numdebs = argc - 1;
320 debs = new char *[numdebs];
321 memcpy(debs, &argv[1], sizeof(char *) * numdebs);
322
323 if (numdebs < 1) ShowHelp();
324
325 for (idx = 0; idx < numdebs; idx++)
326 {
327 DebFile file(debs[idx]);
328 if (file.Go() == false)
329 {
330 fprintf(stderr, _("Cannot read %s\n"), debs[idx]);
331 continue;
332 }
333 // Does the package have templates?
334 if (file.Template != 0 && file.ParseInfo() == true)
335 {
336 // Check to make sure debconf dependencies are
337 // satisfied
338 if (file.DepVer != "" &&
339 pkgCheckDep(file.DepVer.c_str(),
340 debconfver, file.DepOp) == false)
341 continue;
342 if (file.PreDepVer != "" &&
343 pkgCheckDep(file.PreDepVer.c_str(),
344 debconfver, file.PreDepOp) == false)
345 continue;
346
347 WriteConfig(file);
348 }
349 }
350
351
352 delete Map;
353 delete DebFile::Cache;
354
355 return 0;
356 }