debfile.cc 5.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305
  1. #include <stdio.h>
  2. #include <apt-pkg/tagfile.h>
  3. #include <apt-pkg/extracttar.h>
  4. #include <apt-pkg/arfile.h>
  5. #include <apt-pkg/pkgcache.h>
  6. #include "debfile.h"
  7. pkgCache *DebFile::Cache = 0;
  8. DebFile::DebFile(const char *debfile)
  9. : File(debfile, FileFd::ReadOnly), Control(0), Package(0), Version(0), DepVer(0), PreDepVer(0), DepOp(0), PreDepOp(0), Config(0), Template(0), Which(None)
  10. {
  11. }
  12. DebFile::~DebFile()
  13. {
  14. delete [] Control;
  15. delete [] Config;
  16. delete [] Template;
  17. }
  18. char *DebFile::GetInstalledVer(const char *package)
  19. {
  20. char *ver = 0;
  21. pkgCache::PkgIterator Pkg = Cache->FindPkg(package);
  22. if (Pkg.end() == false)
  23. {
  24. pkgCache::VerIterator V = Pkg.CurrentVer();
  25. if (V.end() == false)
  26. {
  27. ver = strdup(V.VerStr());
  28. }
  29. }
  30. return ver;
  31. }
  32. bool DebFile::Go()
  33. {
  34. ARArchive AR(File);
  35. const ARArchive::Member *Member = AR.FindMember("control.tar.gz");
  36. if (Member == 0)
  37. {
  38. fprintf(stderr, "This is not a valid DEB archive.\n");
  39. return false;
  40. }
  41. if (File.Seek(Member->Start) == false)
  42. {
  43. return false;
  44. }
  45. ExtractTar Tar(File, Member->Size);
  46. return Tar.Go(*this);
  47. }
  48. bool DebFile::DoItem(Item &I, int &Fd)
  49. {
  50. if (strcmp(I.Name, "control") == 0)
  51. {
  52. delete [] Control;
  53. Control = new char[I.Size+1];
  54. Control[I.Size] = 0;
  55. Which = IsControl;
  56. ControlLen = I.Size;
  57. // make it call the Process method below. this is so evil
  58. Fd = -2;
  59. }
  60. else if (strcmp(I.Name, "config") == 0)
  61. {
  62. delete [] Config;
  63. Config = new char[I.Size+1];
  64. Config[I.Size] = 0;
  65. Which = IsConfig;
  66. Fd = -2;
  67. }
  68. else if (strcmp(I.Name, "templates") == 0)
  69. {
  70. delete [] Template;
  71. Template = new char[I.Size+1];
  72. Template[I.Size] = 0;
  73. Which = IsTemplate;
  74. Fd = -2;
  75. }
  76. else
  77. {
  78. Fd = -1;
  79. }
  80. return true;
  81. }
  82. bool DebFile::Process(Item &I, const unsigned char *data,
  83. unsigned long size, unsigned long pos)
  84. {
  85. switch (Which)
  86. {
  87. case IsControl:
  88. memcpy(Control + pos, data, size);
  89. break;
  90. case IsConfig:
  91. memcpy(Config + pos, data, size);
  92. break;
  93. case IsTemplate:
  94. memcpy(Template + pos, data, size);
  95. break;
  96. default: /* throw it away */ ;
  97. }
  98. return true;
  99. }
  100. bool DebFile::ParseInfo()
  101. {
  102. if (Control == NULL) return false;
  103. pkgTagSection Section;
  104. Section.Scan(Control, ControlLen);
  105. const char *pkgtmp = Section.FindS("Package").c_str();
  106. Package = CopyString(pkgtmp, strlen(pkgtmp));
  107. Version = GetInstalledVer(Package);
  108. const char *Start, *Stop;
  109. if (Section.Find("Depends", Start, Stop) == true)
  110. {
  111. while (1)
  112. {
  113. char *P = 0, *V = 0;
  114. unsigned int Op;
  115. Start = ParseDepends(Start, Stop, P, V, Op);
  116. if (Start == 0) return false;
  117. if (strcmp(P, "debconf") == 0)
  118. {
  119. DepVer = V;
  120. DepOp = Op;
  121. delete[] P;
  122. break;
  123. }
  124. else
  125. {
  126. delete[] P;
  127. delete[] V;
  128. }
  129. if (Start == Stop) break;
  130. }
  131. }
  132. if (Section.Find("Pre-Depends", Start, Stop) == true)
  133. {
  134. while (1)
  135. {
  136. char *P = 0, *V = 0;
  137. unsigned int Op;
  138. Start = ParseDepends(Start, Stop, P, V, Op);
  139. if (Start == 0) return false;
  140. if (strcmp(P, "debconf") == 0)
  141. {
  142. PreDepVer = V;
  143. PreDepOp = Op;
  144. delete[] P;
  145. break;
  146. }
  147. else
  148. {
  149. delete[] P;
  150. delete[] V;
  151. }
  152. if (Start == Stop) break;
  153. }
  154. }
  155. return true;
  156. }
  157. char *DebFile::CopyString(const char *start, unsigned int len)
  158. {
  159. char *s = new char[len + 1];
  160. s[len] = 0;
  161. memcpy(s, start, len);
  162. return s;
  163. }
  164. const char *DebFile::ParseDepends(const char *Start,const char *Stop,
  165. char *&Package, char *&Ver,
  166. unsigned int &Op)
  167. {
  168. // Strip off leading space
  169. for (;Start != Stop && isspace(*Start) != 0; Start++);
  170. // Parse off the package name
  171. const char *I = Start;
  172. for (;I != Stop && isspace(*I) == 0 && *I != '(' && *I != ')' &&
  173. *I != ',' && *I != '|'; I++);
  174. // Malformed, no '('
  175. if (I != Stop && *I == ')')
  176. return 0;
  177. if (I == Start)
  178. return 0;
  179. // Stash the package name
  180. Package = CopyString(Start, I - Start);
  181. // Skip white space to the '('
  182. for (;I != Stop && isspace(*I) != 0 ; I++);
  183. // Parse a version
  184. if (I != Stop && *I == '(')
  185. {
  186. // Skip the '('
  187. for (I++; I != Stop && isspace(*I) != 0 ; I++);
  188. if (I + 3 >= Stop)
  189. return 0;
  190. // Determine the operator
  191. switch (*I)
  192. {
  193. case '<':
  194. I++;
  195. if (*I == '=')
  196. {
  197. I++;
  198. Op = pkgCache::Dep::LessEq;
  199. break;
  200. }
  201. if (*I == '<')
  202. {
  203. I++;
  204. Op = pkgCache::Dep::Less;
  205. break;
  206. }
  207. // < is the same as <= and << is really Cs < for some reason
  208. Op = pkgCache::Dep::LessEq;
  209. break;
  210. case '>':
  211. I++;
  212. if (*I == '=')
  213. {
  214. I++;
  215. Op = pkgCache::Dep::GreaterEq;
  216. break;
  217. }
  218. if (*I == '>')
  219. {
  220. I++;
  221. Op = pkgCache::Dep::Greater;
  222. break;
  223. }
  224. // > is the same as >= and >> is really Cs > for some reason
  225. Op = pkgCache::Dep::GreaterEq;
  226. break;
  227. case '=':
  228. Op = pkgCache::Dep::Equals;
  229. I++;
  230. break;
  231. // HACK around bad package definitions
  232. default:
  233. Op = pkgCache::Dep::Equals;
  234. break;
  235. }
  236. // Skip whitespace
  237. for (;I != Stop && isspace(*I) != 0; I++);
  238. Start = I;
  239. for (;I != Stop && *I != ')'; I++);
  240. if (I == Stop || Start == I)
  241. return 0;
  242. // Skip trailing whitespace
  243. const char *End = I;
  244. for (; End > Start && isspace(End[-1]); End--);
  245. Ver = CopyString(Start, End - Start);
  246. I++;
  247. }
  248. else
  249. {
  250. Ver = CopyString("", 0);
  251. Op = pkgCache::Dep::NoOp;
  252. }
  253. // Skip whitespace
  254. for (;I != Stop && isspace(*I) != 0; I++);
  255. if (I != Stop && *I == '|')
  256. Op |= pkgCache::Dep::Or;
  257. if (I == Stop || *I == ',' || *I == '|')
  258. {
  259. if (I != Stop)
  260. for (I++; I != Stop && isspace(*I) != 0; I++);
  261. return I;
  262. }
  263. return 0;
  264. }