apt-extracttemplates.cc 9.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381
  1. // -*- mode: cpp; mode: fold -*-
  2. // Description /*{{{*/
  3. // $Id: apt-extracttemplates.cc,v 1.15 2003/07/26 00:00:11 mdz Exp $
  4. /* ######################################################################
  5. APT Extract Templates - Program to extract debconf config and template
  6. files
  7. This is a simple program to extract config and template information
  8. from Debian packages. It can be used to speed up the preconfiguration
  9. process for debconf-enabled packages
  10. ##################################################################### */
  11. /*}}}*/
  12. // Include Files /*{{{*/
  13. #include<config.h>
  14. #include <apt-pkg/init.h>
  15. #include <apt-pkg/cmndline.h>
  16. #include <apt-pkg/pkgcache.h>
  17. #include <apt-pkg/cacheiterators.h>
  18. #include <apt-pkg/configuration.h>
  19. #include <apt-pkg/sourcelist.h>
  20. #include <apt-pkg/pkgcachegen.h>
  21. #include <apt-pkg/version.h>
  22. #include <apt-pkg/tagfile.h>
  23. #include <apt-pkg/debfile.h>
  24. #include <apt-pkg/deblistparser.h>
  25. #include <apt-pkg/error.h>
  26. #include <apt-pkg/strutl.h>
  27. #include <apt-pkg/fileutl.h>
  28. #include <apt-pkg/pkgsystem.h>
  29. #include <apt-pkg/dirstream.h>
  30. #include <apt-pkg/mmap.h>
  31. #include <iostream>
  32. #include <stdio.h>
  33. #include <string.h>
  34. #include <unistd.h>
  35. #include "apt-extracttemplates.h"
  36. #include <apti18n.h>
  37. /*}}}*/
  38. using namespace std;
  39. pkgCache *DebFile::Cache = 0;
  40. // DebFile::DebFile - Construct the DebFile object /*{{{*/
  41. // ---------------------------------------------------------------------
  42. /* */
  43. DebFile::DebFile(const char *debfile)
  44. : File(debfile, FileFd::ReadOnly), Size(0), Control(NULL), ControlLen(0),
  45. DepOp(0), PreDepOp(0), Config(0), Template(0), Which(None)
  46. {
  47. }
  48. /*}}}*/
  49. // DebFile::~DebFile - Destruct the DebFile object /*{{{*/
  50. // ---------------------------------------------------------------------
  51. /* */
  52. DebFile::~DebFile()
  53. {
  54. delete [] Control;
  55. delete [] Config;
  56. delete [] Template;
  57. }
  58. /*}}}*/
  59. // DebFile::GetInstalledVer - Find out the installed version of a pkg /*{{{*/
  60. // ---------------------------------------------------------------------
  61. /* */
  62. string DebFile::GetInstalledVer(const string &package)
  63. {
  64. pkgCache::PkgIterator Pkg = Cache->FindPkg(package);
  65. if (Pkg.end() == false)
  66. {
  67. pkgCache::VerIterator V = Pkg.CurrentVer();
  68. if (V.end() == false)
  69. {
  70. return V.VerStr();
  71. }
  72. }
  73. return string();
  74. }
  75. /*}}}*/
  76. // DebFile::Go - Start extracting a debian package /*{{{*/
  77. // ---------------------------------------------------------------------
  78. /* */
  79. bool DebFile::Go()
  80. {
  81. debDebFile Deb(File);
  82. return Deb.ExtractTarMember(*this, "control.tar");
  83. }
  84. /*}}}*/
  85. // DebFile::DoItem examine element in package and mark /*{{{*/
  86. // ---------------------------------------------------------------------
  87. /* */
  88. bool DebFile::DoItem(Item &I, int &Fd)
  89. {
  90. if (strcmp(I.Name, "control") == 0)
  91. {
  92. delete [] Control;
  93. Control = new char[I.Size+1];
  94. Control[I.Size] = 0;
  95. Which = IsControl;
  96. ControlLen = I.Size;
  97. // make it call the Process method below. this is so evil
  98. Fd = -2;
  99. }
  100. else if (strcmp(I.Name, "config") == 0)
  101. {
  102. delete [] Config;
  103. Config = new char[I.Size+1];
  104. Config[I.Size] = 0;
  105. Which = IsConfig;
  106. Fd = -2;
  107. }
  108. else if (strcmp(I.Name, "templates") == 0)
  109. {
  110. delete [] Template;
  111. Template = new char[I.Size+1];
  112. Template[I.Size] = 0;
  113. Which = IsTemplate;
  114. Fd = -2;
  115. }
  116. else
  117. {
  118. // Ignore it
  119. Fd = -1;
  120. }
  121. return true;
  122. }
  123. /*}}}*/
  124. // DebFile::Process examine element in package and copy /*{{{*/
  125. // ---------------------------------------------------------------------
  126. /* */
  127. bool DebFile::Process(Item &/*I*/, const unsigned char *data,
  128. unsigned long size, unsigned long pos)
  129. {
  130. switch (Which)
  131. {
  132. case IsControl:
  133. memcpy(Control + pos, data, size);
  134. break;
  135. case IsConfig:
  136. memcpy(Config + pos, data, size);
  137. break;
  138. case IsTemplate:
  139. memcpy(Template + pos, data, size);
  140. break;
  141. default: /* throw it away */ ;
  142. }
  143. return true;
  144. }
  145. /*}}}*/
  146. // DebFile::ParseInfo - Parse control file for dependency info /*{{{*/
  147. // ---------------------------------------------------------------------
  148. /* */
  149. bool DebFile::ParseInfo()
  150. {
  151. if (Control == NULL) return false;
  152. pkgTagSection Section;
  153. Section.Scan(Control, ControlLen);
  154. Package = Section.FindS("Package");
  155. Version = GetInstalledVer(Package);
  156. const char *Start, *Stop;
  157. if (Section.Find("Depends", Start, Stop) == true)
  158. {
  159. while (1)
  160. {
  161. string P, V;
  162. unsigned int Op;
  163. Start = debListParser::ParseDepends(Start, Stop, P, V, Op);
  164. if (Start == 0) return false;
  165. if (P == "debconf")
  166. {
  167. DepVer = V;
  168. DepOp = Op;
  169. break;
  170. }
  171. if (Start == Stop) break;
  172. }
  173. }
  174. if (Section.Find("Pre-Depends", Start, Stop) == true)
  175. {
  176. while (1)
  177. {
  178. string P, V;
  179. unsigned int Op;
  180. Start = debListParser::ParseDepends(Start, Stop, P, V, Op);
  181. if (Start == 0) return false;
  182. if (P == "debconf")
  183. {
  184. PreDepVer = V;
  185. PreDepOp = Op;
  186. break;
  187. }
  188. if (Start == Stop) break;
  189. }
  190. }
  191. return true;
  192. }
  193. /*}}}*/
  194. // ShowHelp - show a short help text /*{{{*/
  195. // ---------------------------------------------------------------------
  196. /* */
  197. static int ShowHelp(void)
  198. {
  199. ioprintf(cout,_("%s %s for %s compiled on %s %s\n"),PACKAGE,PACKAGE_VERSION,
  200. COMMON_ARCH,__DATE__,__TIME__);
  201. if (_config->FindB("version") == true)
  202. return 0;
  203. cout <<
  204. _("Usage: apt-extracttemplates file1 [file2 ...]\n"
  205. "\n"
  206. "apt-extracttemplates is a tool to extract config and template info\n"
  207. "from debian packages\n"
  208. "\n"
  209. "Options:\n"
  210. " -h This help text\n"
  211. " -t Set the temp dir\n"
  212. " -c=? Read this configuration file\n"
  213. " -o=? Set an arbitrary configuration option, eg -o dir::cache=/tmp\n");
  214. return 0;
  215. }
  216. /*}}}*/
  217. // WriteFile - write the contents of the passed string to a file /*{{{*/
  218. // ---------------------------------------------------------------------
  219. /* */
  220. static string WriteFile(const char *package, const char *prefix, const char *data)
  221. {
  222. char fn[512];
  223. static int i;
  224. std::string tempdir = GetTempDir();
  225. snprintf(fn, sizeof(fn), "%s/%s.%s.%u%d",
  226. _config->Find("APT::ExtractTemplates::TempDir",
  227. tempdir.c_str()).c_str(),
  228. package, prefix, getpid(), i++);
  229. FileFd f;
  230. if (data == NULL)
  231. data = "";
  232. if (!f.Open(fn, FileFd::WriteTemp, 0600))
  233. {
  234. _error->Errno("ofstream::ofstream",_("Unable to write to %s"),fn);
  235. return string();
  236. }
  237. f.Write(data, strlen(data));
  238. f.Close();
  239. return fn;
  240. }
  241. /*}}}*/
  242. // WriteConfig - write out the config data from a debian package file /*{{{*/
  243. // ---------------------------------------------------------------------
  244. /* */
  245. static void WriteConfig(const DebFile &file)
  246. {
  247. string templatefile = WriteFile(file.Package.c_str(), "template", file.Template);
  248. string configscript = WriteFile(file.Package.c_str(), "config", file.Config);
  249. if (templatefile.empty() == true || configscript.empty() == true)
  250. return;
  251. cout << file.Package << " " << file.Version << " "
  252. << templatefile << " " << configscript << endl;
  253. }
  254. /*}}}*/
  255. // InitCache - initialize the package cache /*{{{*/
  256. // ---------------------------------------------------------------------
  257. /* */
  258. static bool Go(CommandLine &CmdL)
  259. {
  260. // Initialize the apt cache
  261. MMap *Map = 0;
  262. pkgSourceList List;
  263. List.ReadMainList();
  264. pkgCacheGenerator::MakeStatusCache(List,NULL,&Map,true);
  265. if (Map == 0)
  266. return false;
  267. DebFile::Cache = new pkgCache(Map);
  268. if (_error->PendingError() == true)
  269. return false;
  270. // Find out what version of debconf is currently installed
  271. string debconfver = DebFile::GetInstalledVer("debconf");
  272. if (debconfver.empty() == true)
  273. return _error->Error( _("Cannot get debconf version. Is debconf installed?"));
  274. // Process each package passsed in
  275. for (unsigned int I = 0; I != CmdL.FileSize(); I++)
  276. {
  277. // Will pick up the errors later..
  278. DebFile file(CmdL.FileList[I]);
  279. if (file.Go() == false)
  280. {
  281. _error->Error("Prior errors apply to %s",CmdL.FileList[I]);
  282. continue;
  283. }
  284. // Does the package have templates?
  285. if (file.Template != 0 && file.ParseInfo() == true)
  286. {
  287. // Check to make sure debconf dependencies are
  288. // satisfied
  289. // cout << "Check " << file.DepVer << ',' << debconfver << endl;
  290. if (file.DepVer != "" &&
  291. DebFile::Cache->VS->CheckDep(debconfver.c_str(),
  292. file.DepOp,file.DepVer.c_str()
  293. ) == false)
  294. continue;
  295. if (file.PreDepVer != "" &&
  296. DebFile::Cache->VS->CheckDep(debconfver.c_str(),
  297. file.PreDepOp,file.PreDepVer.c_str()
  298. ) == false)
  299. continue;
  300. WriteConfig(file);
  301. }
  302. }
  303. delete Map;
  304. delete DebFile::Cache;
  305. return !_error->PendingError();
  306. }
  307. /*}}}*/
  308. int main(int argc, const char **argv) /*{{{*/
  309. {
  310. CommandLine::Args Args[] = {
  311. {'h',"help","help",0},
  312. {'v',"version","version",0},
  313. {'t',"tempdir","APT::ExtractTemplates::TempDir",CommandLine::HasArg},
  314. {'c',"config-file",0,CommandLine::ConfigFile},
  315. {'o',"option",0,CommandLine::ArbItem},
  316. {0,0,0,0}};
  317. // Set up gettext support
  318. setlocale(LC_ALL,"");
  319. textdomain(PACKAGE);
  320. // Parse the command line and initialize the package library
  321. CommandLine CmdL(Args,_config);
  322. if (pkgInitConfig(*_config) == false ||
  323. CmdL.Parse(argc,argv) == false ||
  324. pkgInitSystem(*_config,_system) == false)
  325. {
  326. _error->DumpErrors();
  327. return 100;
  328. }
  329. // See if the help should be shown
  330. if (_config->FindB("help") == true ||
  331. CmdL.FileSize() == 0)
  332. return ShowHelp();
  333. Go(CmdL);
  334. // Print any errors or warnings found during operation
  335. if (_error->empty() == false)
  336. {
  337. // This goes to stderr..
  338. bool Errors = _error->PendingError();
  339. _error->DumpErrors();
  340. return Errors == true?100:0;
  341. }
  342. return 0;
  343. }
  344. /*}}}*/