3
0

dpkg.c 55 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711171217131714171517161717171817191720172117221723172417251726172717281729173017311732173317341735173617371738173917401741174217431744174517461747174817491750175117521753175417551756175717581759176017611762176317641765176617671768176917701771177217731774177517761777177817791780178117821783178417851786178717881789179017911792179317941795179617971798179918001801180218031804180518061807180818091810181118121813181418151816181718181819
  1. /* vi: set sw=4 ts=4: */
  2. /*
  3. * mini dpkg implementation for busybox.
  4. * this is not meant as a replacement for dpkg
  5. *
  6. * written by glenn mcgrath with the help of others
  7. * copyright (c) 2001 by glenn mcgrath
  8. *
  9. * started life as a busybox implementation of udpkg
  10. *
  11. * licensed under gplv2 or later, see file license in this tarball for details.
  12. */
  13. /*
  14. * known difference between busybox dpkg and the official dpkg that i don't
  15. * consider important, its worth keeping a note of differences anyway, just to
  16. * make it easier to maintain.
  17. * - the first value for the confflile: field isnt placed on a new line.
  18. * - when installing a package the status: field is placed at the end of the
  19. * section, rather than just after the package: field.
  20. *
  21. * bugs that need to be fixed
  22. * - (unknown, please let me know when you find any)
  23. *
  24. */
  25. #include "busybox.h"
  26. #include "unarchive.h"
  27. /* note: if you vary hash_prime sizes be aware,
  28. * 1) tweaking these will have a big effect on how much memory this program uses.
  29. * 2) for computational efficiency these hash tables should be at least 20%
  30. * larger than the maximum number of elements stored in it.
  31. * 3) all _hash_prime's must be a prime number or chaos is assured, if your looking
  32. * for a prime, try http://www.utm.edu/research/primes/lists/small/10000.txt
  33. * 4) if you go bigger than 15 bits you may get into trouble (untested) as its
  34. * sometimes cast to an unsigned int, if you go to 16 bit you will overlap
  35. * int's and chaos is assured, 16381 is the max prime for 14 bit field
  36. */
  37. /* NAME_HASH_PRIME, Stores package names and versions,
  38. * I estimate it should be at least 50% bigger than PACKAGE_HASH_PRIME,
  39. * as there a lot of duplicate version numbers */
  40. #define NAME_HASH_PRIME 16381
  41. /* PACKAGE_HASH_PRIME, Maximum number of unique packages,
  42. * It must not be smaller than STATUS_HASH_PRIME,
  43. * Currently only packages from status_hashtable are stored in here, but in
  44. * future this may be used to store packages not only from a status file,
  45. * but an available_hashtable, and even multiple packages files.
  46. * Package can be stored more than once if they have different versions.
  47. * e.g. The same package may have different versions in the status file
  48. * and available file */
  49. #define PACKAGE_HASH_PRIME 10007
  50. typedef struct edge_s {
  51. unsigned int operator:3;
  52. unsigned int type:4;
  53. unsigned int name:14;
  54. unsigned int version:14;
  55. } edge_t;
  56. typedef struct common_node_s {
  57. unsigned int name:14;
  58. unsigned int version:14;
  59. unsigned int num_of_edges:14;
  60. edge_t **edge;
  61. } common_node_t;
  62. /* Currently it doesnt store packages that have state-status of not-installed
  63. * So it only really has to be the size of the maximum number of packages
  64. * likely to be installed at any one time, so there is a bit of leeway here */
  65. #define STATUS_HASH_PRIME 8191
  66. typedef struct status_node_s {
  67. unsigned int package:14; /* has to fit PACKAGE_HASH_PRIME */
  68. unsigned int status:14; /* has to fit STATUS_HASH_PRIME */
  69. } status_node_t;
  70. /* Were statically declared here, but such a big bss is nommu-unfriendly */
  71. static char **name_hashtable; /* [NAME_HASH_PRIME + 1] */
  72. static common_node_t **package_hashtable; /* [PACKAGE_HASH_PRIME + 1] */
  73. static status_node_t **status_hashtable; /* [STATUS_HASH_PRIME + 1] */
  74. /* Even numbers are for 'extras', like ored dependencies or null */
  75. enum edge_type_e {
  76. EDGE_NULL = 0,
  77. EDGE_PRE_DEPENDS = 1,
  78. EDGE_OR_PRE_DEPENDS = 2,
  79. EDGE_DEPENDS = 3,
  80. EDGE_OR_DEPENDS = 4,
  81. EDGE_REPLACES = 5,
  82. EDGE_PROVIDES = 7,
  83. EDGE_CONFLICTS = 9,
  84. EDGE_SUGGESTS = 11,
  85. EDGE_RECOMMENDS = 13,
  86. EDGE_ENHANCES = 15
  87. };
  88. enum operator_e {
  89. VER_NULL = 0,
  90. VER_EQUAL = 1,
  91. VER_LESS = 2,
  92. VER_LESS_EQUAL = 3,
  93. VER_MORE = 4,
  94. VER_MORE_EQUAL = 5,
  95. VER_ANY = 6
  96. };
  97. enum dpkg_opt_e {
  98. dpkg_opt_purge = 1,
  99. dpkg_opt_remove = 2,
  100. dpkg_opt_unpack = 4,
  101. dpkg_opt_configure = 8,
  102. dpkg_opt_install = 16,
  103. dpkg_opt_package_name = 32,
  104. dpkg_opt_filename = 64,
  105. dpkg_opt_list_installed = 128,
  106. dpkg_opt_force_ignore_depends = 256
  107. };
  108. typedef struct deb_file_s {
  109. char *control_file;
  110. char *filename;
  111. unsigned int package:14;
  112. } deb_file_t;
  113. static void make_hash(const char *key, unsigned int *start, unsigned int *decrement, const int hash_prime)
  114. {
  115. unsigned long int hash_num = key[0];
  116. int len = strlen(key);
  117. int i;
  118. /* Maybe i should have uses a "proper" hashing algorithm here instead
  119. * of making one up myself, seems to be working ok though. */
  120. for (i = 1; i < len; i++) {
  121. /* shifts the ascii based value and adds it to previous value
  122. * shift amount is mod 24 because long int is 32 bit and data
  123. * to be shifted is 8, don't want to shift data to where it has
  124. * no effect*/
  125. hash_num += ((key[i] + key[i-1]) << ((key[i] * i) % 24));
  126. }
  127. *start = (unsigned int) hash_num % hash_prime;
  128. *decrement = (unsigned int) 1 + (hash_num % (hash_prime - 1));
  129. }
  130. /* this adds the key to the hash table */
  131. static int search_name_hashtable(const char *key)
  132. {
  133. unsigned int probe_address = 0;
  134. unsigned int probe_decrement = 0;
  135. // char *temp;
  136. make_hash(key, &probe_address, &probe_decrement, NAME_HASH_PRIME);
  137. while (name_hashtable[probe_address] != NULL) {
  138. if (strcmp(name_hashtable[probe_address], key) == 0) {
  139. return probe_address;
  140. } else {
  141. probe_address -= probe_decrement;
  142. if ((int)probe_address < 0) {
  143. probe_address += NAME_HASH_PRIME;
  144. }
  145. }
  146. }
  147. name_hashtable[probe_address] = xstrdup(key);
  148. return probe_address;
  149. }
  150. /* this DOESNT add the key to the hashtable
  151. * TODO make it consistent with search_name_hashtable
  152. */
  153. static unsigned int search_status_hashtable(const char *key)
  154. {
  155. unsigned int probe_address = 0;
  156. unsigned int probe_decrement = 0;
  157. make_hash(key, &probe_address, &probe_decrement, STATUS_HASH_PRIME);
  158. while (status_hashtable[probe_address] != NULL) {
  159. if (strcmp(key, name_hashtable[package_hashtable[status_hashtable[probe_address]->package]->name]) == 0) {
  160. break;
  161. } else {
  162. probe_address -= probe_decrement;
  163. if ((int)probe_address < 0) {
  164. probe_address += STATUS_HASH_PRIME;
  165. }
  166. }
  167. }
  168. return probe_address;
  169. }
  170. /* Need to rethink version comparison, maybe the official dpkg has something i can use ? */
  171. static int version_compare_part(const char *version1, const char *version2)
  172. {
  173. int upstream_len1 = 0;
  174. int upstream_len2 = 0;
  175. char *name1_char;
  176. char *name2_char;
  177. int len1 = 0;
  178. int len2 = 0;
  179. int tmp_int;
  180. int ver_num1;
  181. int ver_num2;
  182. int ret;
  183. if (version1 == NULL) {
  184. version1 = xstrdup("");
  185. }
  186. if (version2 == NULL) {
  187. version2 = xstrdup("");
  188. }
  189. upstream_len1 = strlen(version1);
  190. upstream_len2 = strlen(version2);
  191. while ((len1 < upstream_len1) || (len2 < upstream_len2)) {
  192. /* Compare non-digit section */
  193. tmp_int = strcspn(&version1[len1], "0123456789");
  194. name1_char = xstrndup(&version1[len1], tmp_int);
  195. len1 += tmp_int;
  196. tmp_int = strcspn(&version2[len2], "0123456789");
  197. name2_char = xstrndup(&version2[len2], tmp_int);
  198. len2 += tmp_int;
  199. tmp_int = strcmp(name1_char, name2_char);
  200. free(name1_char);
  201. free(name2_char);
  202. if (tmp_int != 0) {
  203. ret = tmp_int;
  204. goto cleanup_version_compare_part;
  205. }
  206. /* Compare digits */
  207. tmp_int = strspn(&version1[len1], "0123456789");
  208. name1_char = xstrndup(&version1[len1], tmp_int);
  209. len1 += tmp_int;
  210. tmp_int = strspn(&version2[len2], "0123456789");
  211. name2_char = xstrndup(&version2[len2], tmp_int);
  212. len2 += tmp_int;
  213. ver_num1 = atoi(name1_char);
  214. ver_num2 = atoi(name2_char);
  215. free(name1_char);
  216. free(name2_char);
  217. if (ver_num1 < ver_num2) {
  218. ret = -1;
  219. goto cleanup_version_compare_part;
  220. }
  221. else if (ver_num1 > ver_num2) {
  222. ret = 1;
  223. goto cleanup_version_compare_part;
  224. }
  225. }
  226. ret = 0;
  227. cleanup_version_compare_part:
  228. return ret;
  229. }
  230. /* if ver1 < ver2 return -1,
  231. * if ver1 = ver2 return 0,
  232. * if ver1 > ver2 return 1,
  233. */
  234. static int version_compare(const unsigned int ver1, const unsigned int ver2)
  235. {
  236. char *ch_ver1 = name_hashtable[ver1];
  237. char *ch_ver2 = name_hashtable[ver2];
  238. char epoch1, epoch2;
  239. char *deb_ver1, *deb_ver2;
  240. char *ver1_ptr, *ver2_ptr;
  241. char *upstream_ver1;
  242. char *upstream_ver2;
  243. int result;
  244. /* Compare epoch */
  245. if (ch_ver1[1] == ':') {
  246. epoch1 = ch_ver1[0];
  247. ver1_ptr = strchr(ch_ver1, ':') + 1;
  248. } else {
  249. epoch1 = '0';
  250. ver1_ptr = ch_ver1;
  251. }
  252. if (ch_ver2[1] == ':') {
  253. epoch2 = ch_ver2[0];
  254. ver2_ptr = strchr(ch_ver2, ':') + 1;
  255. } else {
  256. epoch2 = '0';
  257. ver2_ptr = ch_ver2;
  258. }
  259. if (epoch1 < epoch2) {
  260. return -1;
  261. }
  262. else if (epoch1 > epoch2) {
  263. return 1;
  264. }
  265. /* Compare upstream version */
  266. upstream_ver1 = xstrdup(ver1_ptr);
  267. upstream_ver2 = xstrdup(ver2_ptr);
  268. /* Chop off debian version, and store for later use */
  269. deb_ver1 = strrchr(upstream_ver1, '-');
  270. deb_ver2 = strrchr(upstream_ver2, '-');
  271. if (deb_ver1) {
  272. deb_ver1[0] = '\0';
  273. deb_ver1++;
  274. }
  275. if (deb_ver2) {
  276. deb_ver2[0] = '\0';
  277. deb_ver2++;
  278. }
  279. result = version_compare_part(upstream_ver1, upstream_ver2);
  280. if (!result)
  281. /* Compare debian versions */
  282. result = version_compare_part(deb_ver1, deb_ver2);
  283. free(upstream_ver1);
  284. free(upstream_ver2);
  285. return result;
  286. }
  287. static int test_version(const unsigned int version1, const unsigned int version2, const unsigned int operator)
  288. {
  289. const int version_result = version_compare(version1, version2);
  290. switch (operator) {
  291. case VER_ANY:
  292. return TRUE;
  293. case VER_EQUAL:
  294. if (version_result == 0) {
  295. return TRUE;
  296. }
  297. break;
  298. case VER_LESS:
  299. if (version_result < 0) {
  300. return TRUE;
  301. }
  302. break;
  303. case VER_LESS_EQUAL:
  304. if (version_result <= 0) {
  305. return TRUE;
  306. }
  307. break;
  308. case VER_MORE:
  309. if (version_result > 0) {
  310. return TRUE;
  311. }
  312. break;
  313. case VER_MORE_EQUAL:
  314. if (version_result >= 0) {
  315. return TRUE;
  316. }
  317. break;
  318. }
  319. return FALSE;
  320. }
  321. static int search_package_hashtable(const unsigned int name, const unsigned int version, const unsigned int operator)
  322. {
  323. unsigned int probe_address = 0;
  324. unsigned int probe_decrement = 0;
  325. make_hash(name_hashtable[name], &probe_address, &probe_decrement, PACKAGE_HASH_PRIME);
  326. while (package_hashtable[probe_address] != NULL) {
  327. if (package_hashtable[probe_address]->name == name) {
  328. if (operator == VER_ANY) {
  329. return probe_address;
  330. }
  331. if (test_version(package_hashtable[probe_address]->version, version, operator)) {
  332. return probe_address;
  333. }
  334. }
  335. probe_address -= probe_decrement;
  336. if ((int)probe_address < 0) {
  337. probe_address += PACKAGE_HASH_PRIME;
  338. }
  339. }
  340. return probe_address;
  341. }
  342. /*
  343. * This function searches through the entire package_hashtable looking
  344. * for a package which provides "needle". It returns the index into
  345. * the package_hashtable for the providing package.
  346. *
  347. * needle is the index into name_hashtable of the package we are
  348. * looking for.
  349. *
  350. * start_at is the index in the package_hashtable to start looking
  351. * at. If start_at is -1 then start at the beginning. This is to allow
  352. * for repeated searches since more than one package might provide
  353. * needle.
  354. *
  355. * FIXME: I don't think this is very efficient, but I thought I'd keep
  356. * it simple for now until it proves to be a problem.
  357. */
  358. static int search_for_provides(int needle, int start_at) {
  359. int i, j;
  360. common_node_t *p;
  361. for (i = start_at + 1; i < PACKAGE_HASH_PRIME; i++) {
  362. p = package_hashtable[i];
  363. if (p == NULL) continue;
  364. for (j = 0; j < p->num_of_edges; j++)
  365. if (p->edge[j]->type == EDGE_PROVIDES && p->edge[j]->name == needle)
  366. return i;
  367. }
  368. return -1;
  369. }
  370. /*
  371. * Add an edge to a node
  372. */
  373. static void add_edge_to_node(common_node_t *node, edge_t *edge)
  374. {
  375. node->num_of_edges++;
  376. node->edge = xrealloc(node->edge, sizeof(edge_t) * (node->num_of_edges + 1));
  377. node->edge[node->num_of_edges - 1] = edge;
  378. }
  379. /*
  380. * Create one new node and one new edge for every dependency.
  381. *
  382. * Dependencies which contain multiple alternatives are represented as
  383. * an EDGE_OR_PRE_DEPENDS or EDGE_OR_DEPENDS node, followed by a
  384. * number of EDGE_PRE_DEPENDS or EDGE_DEPENDS nodes. The name field of
  385. * the OR edge contains the full dependency string while the version
  386. * field contains the number of EDGE nodes which follow as part of
  387. * this alternative.
  388. */
  389. static void add_split_dependencies(common_node_t *parent_node, const char *whole_line, unsigned int edge_type)
  390. {
  391. char *line = xstrdup(whole_line);
  392. char *line2;
  393. char *line_ptr1 = NULL;
  394. char *line_ptr2 = NULL;
  395. char *field;
  396. char *field2;
  397. char *version;
  398. edge_t *edge;
  399. edge_t *or_edge;
  400. int offset_ch;
  401. field = strtok_r(line, ",", &line_ptr1);
  402. do {
  403. /* skip leading spaces */
  404. field += strspn(field, " ");
  405. line2 = xstrdup(field);
  406. field2 = strtok_r(line2, "|", &line_ptr2);
  407. if ((edge_type == EDGE_DEPENDS || edge_type == EDGE_PRE_DEPENDS) &&
  408. (strcmp(field, field2) != 0)) {
  409. or_edge = (edge_t *)xmalloc(sizeof(edge_t));
  410. or_edge->type = edge_type + 1;
  411. } else {
  412. or_edge = NULL;
  413. }
  414. if (or_edge) {
  415. or_edge->name = search_name_hashtable(field);
  416. or_edge->version = 0; // tracks the number of altenatives
  417. add_edge_to_node(parent_node, or_edge);
  418. }
  419. do {
  420. edge = (edge_t *) xmalloc(sizeof(edge_t));
  421. edge->type = edge_type;
  422. /* Skip any extra leading spaces */
  423. field2 += strspn(field2, " ");
  424. /* Get dependency version info */
  425. version = strchr(field2, '(');
  426. if (version == NULL) {
  427. edge->operator = VER_ANY;
  428. /* Get the versions hash number, adding it if the number isnt already in there */
  429. edge->version = search_name_hashtable("ANY");
  430. } else {
  431. /* Skip leading ' ' or '(' */
  432. version += strspn(field2, " ");
  433. version += strspn(version, "(");
  434. /* Calculate length of any operator characters */
  435. offset_ch = strspn(version, "<=>");
  436. /* Determine operator */
  437. if (offset_ch > 0) {
  438. if (strncmp(version, "=", offset_ch) == 0) {
  439. edge->operator = VER_EQUAL;
  440. }
  441. else if (strncmp(version, "<<", offset_ch) == 0) {
  442. edge->operator = VER_LESS;
  443. }
  444. else if (strncmp(version, "<=", offset_ch) == 0) {
  445. edge->operator = VER_LESS_EQUAL;
  446. }
  447. else if (strncmp(version, ">>", offset_ch) == 0) {
  448. edge->operator = VER_MORE;
  449. }
  450. else if (strncmp(version, ">=", offset_ch) == 0) {
  451. edge->operator = VER_MORE_EQUAL;
  452. } else {
  453. bb_error_msg_and_die("illegal operator");
  454. }
  455. }
  456. /* skip to start of version numbers */
  457. version += offset_ch;
  458. version += strspn(version, " ");
  459. /* Truncate version at trailing ' ' or ')' */
  460. version[strcspn(version, " )")] = '\0';
  461. /* Get the versions hash number, adding it if the number isnt already in there */
  462. edge->version = search_name_hashtable(version);
  463. }
  464. /* Get the dependency name */
  465. field2[strcspn(field2, " (")] = '\0';
  466. edge->name = search_name_hashtable(field2);
  467. if (or_edge)
  468. or_edge->version++;
  469. add_edge_to_node(parent_node, edge);
  470. } while ((field2 = strtok_r(NULL, "|", &line_ptr2)) != NULL);
  471. free(line2);
  472. } while ((field = strtok_r(NULL, ",", &line_ptr1)) != NULL);
  473. free(line);
  474. return;
  475. }
  476. static void free_package(common_node_t *node)
  477. {
  478. unsigned i;
  479. if (node) {
  480. for (i = 0; i < node->num_of_edges; i++) {
  481. free(node->edge[i]);
  482. }
  483. free(node->edge);
  484. free(node);
  485. }
  486. }
  487. /*
  488. * Gets the next package field from package_buffer, seperated into the field name
  489. * and field value, it returns the int offset to the first character of the next field
  490. */
  491. static int read_package_field(const char *package_buffer, char **field_name, char **field_value)
  492. {
  493. int offset_name_start = 0;
  494. int offset_name_end = 0;
  495. int offset_value_start = 0;
  496. int offset_value_end = 0;
  497. int offset = 0;
  498. int next_offset;
  499. int name_length;
  500. int value_length;
  501. int exit_flag = FALSE;
  502. if (package_buffer == NULL) {
  503. *field_name = NULL;
  504. *field_value = NULL;
  505. return -1;
  506. }
  507. while (1) {
  508. next_offset = offset + 1;
  509. switch (package_buffer[offset]) {
  510. case '\0':
  511. exit_flag = TRUE;
  512. break;
  513. case ':':
  514. if (offset_name_end == 0) {
  515. offset_name_end = offset;
  516. offset_value_start = next_offset;
  517. }
  518. /* TODO: Name might still have trailing spaces if ':' isnt
  519. * immediately after name */
  520. break;
  521. case '\n':
  522. /* TODO: The char next_offset may be out of bounds */
  523. if (package_buffer[next_offset] != ' ') {
  524. exit_flag = TRUE;
  525. break;
  526. }
  527. case '\t':
  528. case ' ':
  529. /* increment the value start point if its a just filler */
  530. if (offset_name_start == offset) {
  531. offset_name_start++;
  532. }
  533. if (offset_value_start == offset) {
  534. offset_value_start++;
  535. }
  536. break;
  537. }
  538. if (exit_flag) {
  539. /* Check that the names are valid */
  540. offset_value_end = offset;
  541. name_length = offset_name_end - offset_name_start;
  542. value_length = offset_value_end - offset_value_start;
  543. if (name_length == 0) {
  544. break;
  545. }
  546. if ((name_length > 0) && (value_length > 0)) {
  547. break;
  548. }
  549. /* If not valid, start fresh with next field */
  550. exit_flag = FALSE;
  551. offset_name_start = offset + 1;
  552. offset_name_end = 0;
  553. offset_value_start = offset + 1;
  554. offset_value_end = offset + 1;
  555. offset++;
  556. }
  557. offset++;
  558. }
  559. if (name_length == 0) {
  560. *field_name = NULL;
  561. } else {
  562. *field_name = xstrndup(&package_buffer[offset_name_start], name_length);
  563. }
  564. if (value_length > 0) {
  565. *field_value = xstrndup(&package_buffer[offset_value_start], value_length);
  566. } else {
  567. *field_value = NULL;
  568. }
  569. return next_offset;
  570. }
  571. static unsigned int fill_package_struct(char *control_buffer)
  572. {
  573. static const char *const field_names[] = { "Package", "Version",
  574. "Pre-Depends", "Depends","Replaces", "Provides",
  575. "Conflicts", "Suggests", "Recommends", "Enhances", 0
  576. };
  577. common_node_t *new_node = (common_node_t *) xzalloc(sizeof(common_node_t));
  578. char *field_name;
  579. char *field_value;
  580. int field_start = 0;
  581. int num = -1;
  582. int buffer_length = strlen(control_buffer);
  583. new_node->version = search_name_hashtable("unknown");
  584. while (field_start < buffer_length) {
  585. unsigned field_num;
  586. field_start += read_package_field(&control_buffer[field_start],
  587. &field_name, &field_value);
  588. if (field_name == NULL) {
  589. goto fill_package_struct_cleanup; /* Oh no, the dreaded goto statement ! */
  590. }
  591. field_num = index_in_str_array(field_names, field_name);
  592. switch (field_num) {
  593. case 0: /* Package */
  594. new_node->name = search_name_hashtable(field_value);
  595. break;
  596. case 1: /* Version */
  597. new_node->version = search_name_hashtable(field_value);
  598. break;
  599. case 2: /* Pre-Depends */
  600. add_split_dependencies(new_node, field_value, EDGE_PRE_DEPENDS);
  601. break;
  602. case 3: /* Depends */
  603. add_split_dependencies(new_node, field_value, EDGE_DEPENDS);
  604. break;
  605. case 4: /* Replaces */
  606. add_split_dependencies(new_node, field_value, EDGE_REPLACES);
  607. break;
  608. case 5: /* Provides */
  609. add_split_dependencies(new_node, field_value, EDGE_PROVIDES);
  610. break;
  611. case 6: /* Conflicts */
  612. add_split_dependencies(new_node, field_value, EDGE_CONFLICTS);
  613. break;
  614. case 7: /* Suggests */
  615. add_split_dependencies(new_node, field_value, EDGE_SUGGESTS);
  616. break;
  617. case 8: /* Recommends */
  618. add_split_dependencies(new_node, field_value, EDGE_RECOMMENDS);
  619. break;
  620. case 9: /* Enhances */
  621. add_split_dependencies(new_node, field_value, EDGE_ENHANCES);
  622. break;
  623. }
  624. fill_package_struct_cleanup:
  625. free(field_name);
  626. free(field_value);
  627. }
  628. if (new_node->version == search_name_hashtable("unknown")) {
  629. free_package(new_node);
  630. return -1;
  631. }
  632. num = search_package_hashtable(new_node->name, new_node->version, VER_EQUAL);
  633. if (package_hashtable[num] == NULL) {
  634. package_hashtable[num] = new_node;
  635. } else {
  636. free_package(new_node);
  637. }
  638. return num;
  639. }
  640. /* if num = 1, it returns the want status, 2 returns flag, 3 returns status */
  641. static unsigned int get_status(const unsigned int status_node, const int num)
  642. {
  643. char *status_string = name_hashtable[status_hashtable[status_node]->status];
  644. char *state_sub_string;
  645. unsigned int state_sub_num;
  646. int len;
  647. int i;
  648. /* set tmp_string to point to the start of the word number */
  649. for (i = 1; i < num; i++) {
  650. /* skip past a word */
  651. status_string += strcspn(status_string, " ");
  652. /* skip past the separating spaces */
  653. status_string += strspn(status_string, " ");
  654. }
  655. len = strcspn(status_string, " \n");
  656. state_sub_string = xstrndup(status_string, len);
  657. state_sub_num = search_name_hashtable(state_sub_string);
  658. free(state_sub_string);
  659. return state_sub_num;
  660. }
  661. static void set_status(const unsigned int status_node_num, const char *new_value, const int position)
  662. {
  663. const unsigned int new_value_len = strlen(new_value);
  664. const unsigned int new_value_num = search_name_hashtable(new_value);
  665. unsigned int want = get_status(status_node_num, 1);
  666. unsigned int flag = get_status(status_node_num, 2);
  667. unsigned int status = get_status(status_node_num, 3);
  668. int want_len = strlen(name_hashtable[want]);
  669. int flag_len = strlen(name_hashtable[flag]);
  670. int status_len = strlen(name_hashtable[status]);
  671. char *new_status;
  672. switch (position) {
  673. case 1:
  674. want = new_value_num;
  675. want_len = new_value_len;
  676. break;
  677. case 2:
  678. flag = new_value_num;
  679. flag_len = new_value_len;
  680. break;
  681. case 3:
  682. status = new_value_num;
  683. status_len = new_value_len;
  684. break;
  685. default:
  686. bb_error_msg_and_die("DEBUG ONLY: this shouldnt happen");
  687. }
  688. new_status = xasprintf("%s %s %s", name_hashtable[want], name_hashtable[flag], name_hashtable[status]);
  689. status_hashtable[status_node_num]->status = search_name_hashtable(new_status);
  690. free(new_status);
  691. return;
  692. }
  693. static const char *describe_status(int status_num) {
  694. int status_want, status_state ;
  695. if (status_hashtable[status_num] == NULL || status_hashtable[status_num]->status == 0)
  696. return "is not installed or flagged to be installed\n";
  697. status_want = get_status(status_num, 1);
  698. status_state = get_status(status_num, 3);
  699. if (status_state == search_name_hashtable("installed")) {
  700. if (status_want == search_name_hashtable("install"))
  701. return "is installed";
  702. if (status_want == search_name_hashtable("deinstall"))
  703. return "is marked to be removed";
  704. if (status_want == search_name_hashtable("purge"))
  705. return "is marked to be purged";
  706. }
  707. if (status_want == search_name_hashtable("unknown"))
  708. return "is in an indeterminate state";
  709. if (status_want == search_name_hashtable("install"))
  710. return "is marked to be installed";
  711. return "is not installed or flagged to be installed";
  712. }
  713. static void index_status_file(const char *filename)
  714. {
  715. FILE *status_file;
  716. char *control_buffer;
  717. char *status_line;
  718. status_node_t *status_node = NULL;
  719. unsigned int status_num;
  720. status_file = xfopen(filename, "r");
  721. while ((control_buffer = xmalloc_fgets_str(status_file, "\n\n")) != NULL) {
  722. const unsigned int package_num = fill_package_struct(control_buffer);
  723. if (package_num != -1) {
  724. status_node = xmalloc(sizeof(status_node_t));
  725. /* fill_package_struct doesnt handle the status field */
  726. status_line = strstr(control_buffer, "Status:");
  727. if (status_line != NULL) {
  728. status_line += 7;
  729. status_line += strspn(status_line, " \n\t");
  730. status_line = xstrndup(status_line, strcspn(status_line, "\n"));
  731. status_node->status = search_name_hashtable(status_line);
  732. free(status_line);
  733. }
  734. status_node->package = package_num;
  735. status_num = search_status_hashtable(name_hashtable[package_hashtable[status_node->package]->name]);
  736. status_hashtable[status_num] = status_node;
  737. }
  738. free(control_buffer);
  739. }
  740. fclose(status_file);
  741. return;
  742. }
  743. static void write_buffer_no_status(FILE *new_status_file, const char *control_buffer)
  744. {
  745. char *name;
  746. char *value;
  747. int start = 0;
  748. while (1) {
  749. start += read_package_field(&control_buffer[start], &name, &value);
  750. if (name == NULL) {
  751. break;
  752. }
  753. if (strcmp(name, "Status") != 0) {
  754. fprintf(new_status_file, "%s: %s\n", name, value);
  755. }
  756. }
  757. return;
  758. }
  759. /* This could do with a cleanup */
  760. static void write_status_file(deb_file_t **deb_file)
  761. {
  762. FILE *old_status_file = xfopen("/var/lib/dpkg/status", "r");
  763. FILE *new_status_file = xfopen("/var/lib/dpkg/status.udeb", "w");
  764. char *package_name;
  765. char *status_from_file;
  766. char *control_buffer = NULL;
  767. char *tmp_string;
  768. int status_num;
  769. int field_start = 0;
  770. int write_flag;
  771. int i = 0;
  772. /* Update previously known packages */
  773. while ((control_buffer = xmalloc_fgets_str(old_status_file, "\n\n")) != NULL) {
  774. if ((tmp_string = strstr(control_buffer, "Package:")) == NULL) {
  775. continue;
  776. }
  777. tmp_string += 8;
  778. tmp_string += strspn(tmp_string, " \n\t");
  779. package_name = xstrndup(tmp_string, strcspn(tmp_string, "\n"));
  780. write_flag = FALSE;
  781. tmp_string = strstr(control_buffer, "Status:");
  782. if (tmp_string != NULL) {
  783. /* Seperate the status value from the control buffer */
  784. tmp_string += 7;
  785. tmp_string += strspn(tmp_string, " \n\t");
  786. status_from_file = xstrndup(tmp_string, strcspn(tmp_string, "\n"));
  787. } else {
  788. status_from_file = NULL;
  789. }
  790. /* Find this package in the status hashtable */
  791. status_num = search_status_hashtable(package_name);
  792. if (status_hashtable[status_num] != NULL) {
  793. const char *status_from_hashtable = name_hashtable[status_hashtable[status_num]->status];
  794. if (strcmp(status_from_file, status_from_hashtable) != 0) {
  795. /* New status isnt exactly the same as old status */
  796. const int state_status = get_status(status_num, 3);
  797. if ((strcmp("installed", name_hashtable[state_status]) == 0) ||
  798. (strcmp("unpacked", name_hashtable[state_status]) == 0)) {
  799. /* We need to add the control file from the package */
  800. i = 0;
  801. while (deb_file[i] != NULL) {
  802. if (strcmp(package_name, name_hashtable[package_hashtable[deb_file[i]->package]->name]) == 0) {
  803. /* Write a status file entry with a modified status */
  804. /* remove trailing \n's */
  805. write_buffer_no_status(new_status_file, deb_file[i]->control_file);
  806. set_status(status_num, "ok", 2);
  807. fprintf(new_status_file, "Status: %s\n\n",
  808. name_hashtable[status_hashtable[status_num]->status]);
  809. write_flag = TRUE;
  810. break;
  811. }
  812. i++;
  813. }
  814. /* This is temperary, debugging only */
  815. if (deb_file[i] == NULL) {
  816. bb_error_msg_and_die("ALERT: cannot find a control file, "
  817. "your status file may be broken, status may be "
  818. "incorrect for %s", package_name);
  819. }
  820. }
  821. else if (strcmp("not-installed", name_hashtable[state_status]) == 0) {
  822. /* Only write the Package, Status, Priority and Section lines */
  823. fprintf(new_status_file, "Package: %s\n", package_name);
  824. fprintf(new_status_file, "Status: %s\n", status_from_hashtable);
  825. while (1) {
  826. char *field_name;
  827. char *field_value;
  828. field_start += read_package_field(&control_buffer[field_start], &field_name, &field_value);
  829. if (field_name == NULL) {
  830. break;
  831. }
  832. if ((strcmp(field_name, "Priority") == 0) ||
  833. (strcmp(field_name, "Section") == 0)) {
  834. fprintf(new_status_file, "%s: %s\n", field_name, field_value);
  835. }
  836. }
  837. write_flag = TRUE;
  838. fputs("\n", new_status_file);
  839. }
  840. else if (strcmp("config-files", name_hashtable[state_status]) == 0) {
  841. /* only change the status line */
  842. while (1) {
  843. char *field_name;
  844. char *field_value;
  845. field_start += read_package_field(&control_buffer[field_start], &field_name, &field_value);
  846. if (field_name == NULL) {
  847. break;
  848. }
  849. /* Setup start point for next field */
  850. if (strcmp(field_name, "Status") == 0) {
  851. fprintf(new_status_file, "Status: %s\n", status_from_hashtable);
  852. } else {
  853. fprintf(new_status_file, "%s: %s\n", field_name, field_value);
  854. }
  855. }
  856. write_flag = TRUE;
  857. fputs("\n", new_status_file);
  858. }
  859. }
  860. }
  861. /* If the package from the status file wasnt handle above, do it now*/
  862. if (! write_flag) {
  863. fprintf(new_status_file, "%s\n\n", control_buffer);
  864. }
  865. free(status_from_file);
  866. free(package_name);
  867. free(control_buffer);
  868. }
  869. /* Write any new packages */
  870. for (i = 0; deb_file[i] != NULL; i++) {
  871. status_num = search_status_hashtable(name_hashtable[package_hashtable[deb_file[i]->package]->name]);
  872. if (strcmp("reinstreq", name_hashtable[get_status(status_num, 2)]) == 0) {
  873. write_buffer_no_status(new_status_file, deb_file[i]->control_file);
  874. set_status(status_num, "ok", 2);
  875. fprintf(new_status_file, "Status: %s\n\n", name_hashtable[status_hashtable[status_num]->status]);
  876. }
  877. }
  878. fclose(old_status_file);
  879. fclose(new_status_file);
  880. /* Create a separate backfile to dpkg */
  881. if (rename("/var/lib/dpkg/status", "/var/lib/dpkg/status.udeb.bak") == -1) {
  882. struct stat stat_buf;
  883. xstat("/var/lib/dpkg/status", &stat_buf);
  884. /* Its ok if renaming the status file fails because status
  885. * file doesnt exist, maybe we are starting from scratch */
  886. bb_error_msg("no status file found, creating new one");
  887. }
  888. if (rename("/var/lib/dpkg/status.udeb", "/var/lib/dpkg/status") == -1) {
  889. bb_error_msg_and_die("DANGER: cannot create status file, "
  890. "you need to manually repair your status file");
  891. }
  892. }
  893. /* This function returns TRUE if the given package can satisfy a
  894. * dependency of type depend_type.
  895. *
  896. * A pre-depends is satisfied only if a package is already installed,
  897. * which a regular depends can be satisfied by a package which we want
  898. * to install.
  899. */
  900. static int package_satisfies_dependency(int package, int depend_type)
  901. {
  902. int status_num = search_status_hashtable(name_hashtable[package_hashtable[package]->name]);
  903. /* status could be unknown if package is a pure virtual
  904. * provides which cannot satisfy any dependency by itself.
  905. */
  906. if (status_hashtable[status_num] == NULL)
  907. return 0;
  908. switch (depend_type) {
  909. case EDGE_PRE_DEPENDS: return get_status(status_num, 3) == search_name_hashtable("installed");
  910. case EDGE_DEPENDS: return get_status(status_num, 1) == search_name_hashtable("install");
  911. }
  912. return 0;
  913. }
  914. static int check_deps(deb_file_t **deb_file, int deb_start, int dep_max_count)
  915. {
  916. int *conflicts = NULL;
  917. int conflicts_num = 0;
  918. int i = deb_start;
  919. int j;
  920. /* Check for conflicts
  921. * TODO: TEST if conflicts with other packages to be installed
  922. *
  923. * Add install packages and the packages they provide
  924. * to the list of files to check conflicts for
  925. */
  926. /* Create array of package numbers to check against
  927. * installed package for conflicts*/
  928. while (deb_file[i] != NULL) {
  929. const unsigned int package_num = deb_file[i]->package;
  930. conflicts = xrealloc(conflicts, sizeof(int) * (conflicts_num + 1));
  931. conflicts[conflicts_num] = package_num;
  932. conflicts_num++;
  933. /* add provides to conflicts list */
  934. for (j = 0; j < package_hashtable[package_num]->num_of_edges; j++) {
  935. if (package_hashtable[package_num]->edge[j]->type == EDGE_PROVIDES) {
  936. const int conflicts_package_num = search_package_hashtable(
  937. package_hashtable[package_num]->edge[j]->name,
  938. package_hashtable[package_num]->edge[j]->version,
  939. package_hashtable[package_num]->edge[j]->operator);
  940. if (package_hashtable[conflicts_package_num] == NULL) {
  941. /* create a new package */
  942. common_node_t *new_node = (common_node_t *) xzalloc(sizeof(common_node_t));
  943. new_node->name = package_hashtable[package_num]->edge[j]->name;
  944. new_node->version = package_hashtable[package_num]->edge[j]->version;
  945. package_hashtable[conflicts_package_num] = new_node;
  946. }
  947. conflicts = xrealloc(conflicts, sizeof(int) * (conflicts_num + 1));
  948. conflicts[conflicts_num] = conflicts_package_num;
  949. conflicts_num++;
  950. }
  951. }
  952. i++;
  953. }
  954. /* Check conflicts */
  955. i = 0;
  956. while (deb_file[i] != NULL) {
  957. const common_node_t *package_node = package_hashtable[deb_file[i]->package];
  958. int status_num = 0;
  959. status_num = search_status_hashtable(name_hashtable[package_node->name]);
  960. if (get_status(status_num, 3) == search_name_hashtable("installed")) {
  961. i++;
  962. continue;
  963. }
  964. for (j = 0; j < package_node->num_of_edges; j++) {
  965. const edge_t *package_edge = package_node->edge[j];
  966. if (package_edge->type == EDGE_CONFLICTS) {
  967. const unsigned int package_num =
  968. search_package_hashtable(package_edge->name,
  969. package_edge->version,
  970. package_edge->operator);
  971. int result = 0;
  972. if (package_hashtable[package_num] != NULL) {
  973. status_num = search_status_hashtable(name_hashtable[package_hashtable[package_num]->name]);
  974. if (get_status(status_num, 1) == search_name_hashtable("install")) {
  975. result = test_version(package_hashtable[deb_file[i]->package]->version,
  976. package_edge->version, package_edge->operator);
  977. }
  978. }
  979. if (result) {
  980. bb_error_msg_and_die("package %s conflicts with %s",
  981. name_hashtable[package_node->name],
  982. name_hashtable[package_edge->name]);
  983. }
  984. }
  985. }
  986. i++;
  987. }
  988. /* Check dependendcies */
  989. for (i = 0; i < PACKAGE_HASH_PRIME; i++) {
  990. int status_num = 0;
  991. int number_of_alternatives = 0;
  992. const edge_t * root_of_alternatives = NULL;
  993. const common_node_t *package_node = package_hashtable[i];
  994. /* If the package node does not exist then this
  995. * package is a virtual one. In which case there are
  996. * no dependencies to check.
  997. */
  998. if (package_node == NULL) continue;
  999. status_num = search_status_hashtable(name_hashtable[package_node->name]);
  1000. /* If there is no status then this package is a
  1001. * virtual one provided by something else. In which
  1002. * case there are no dependencies to check.
  1003. */
  1004. if (status_hashtable[status_num] == NULL) continue;
  1005. /* If we don't want this package installed then we may
  1006. * as well ignore it's dependencies.
  1007. */
  1008. if (get_status(status_num, 1) != search_name_hashtable("install")) {
  1009. continue;
  1010. }
  1011. /* This code is tested only for EDGE_DEPENDS, since I
  1012. * have no suitable pre-depends available. There is no
  1013. * reason that it shouldn't work though :-)
  1014. */
  1015. for (j = 0; j < package_node->num_of_edges; j++) {
  1016. const edge_t *package_edge = package_node->edge[j];
  1017. unsigned int package_num;
  1018. if (package_edge->type == EDGE_OR_PRE_DEPENDS ||
  1019. package_edge->type == EDGE_OR_DEPENDS) { /* start an EDGE_OR_ list */
  1020. number_of_alternatives = package_edge->version;
  1021. root_of_alternatives = package_edge;
  1022. continue;
  1023. } else if (number_of_alternatives == 0) { /* not in the middle of an EDGE_OR_ list */
  1024. number_of_alternatives = 1;
  1025. root_of_alternatives = NULL;
  1026. }
  1027. package_num = search_package_hashtable(package_edge->name, package_edge->version, package_edge->operator);
  1028. if (package_edge->type == EDGE_PRE_DEPENDS ||
  1029. package_edge->type == EDGE_DEPENDS) {
  1030. int result=1;
  1031. status_num = 0;
  1032. /* If we are inside an alternative then check
  1033. * this edge is the right type.
  1034. *
  1035. * EDGE_DEPENDS == OR_DEPENDS -1
  1036. * EDGE_PRE_DEPENDS == OR_PRE_DEPENDS -1
  1037. */
  1038. if (root_of_alternatives && package_edge->type != root_of_alternatives->type - 1)
  1039. bb_error_msg_and_die("fatal error, package dependencies corrupt: %d != %d - 1",
  1040. package_edge->type, root_of_alternatives->type);
  1041. if (package_hashtable[package_num] != NULL)
  1042. result = !package_satisfies_dependency(package_num, package_edge->type);
  1043. if (result) { /* check for other package which provide what we are looking for */
  1044. int provider = -1;
  1045. while ((provider = search_for_provides(package_edge->name, provider)) > -1) {
  1046. if (package_hashtable[provider] == NULL) {
  1047. puts("Have a provider but no package information for it");
  1048. continue;
  1049. }
  1050. result = !package_satisfies_dependency(provider, package_edge->type);
  1051. if (result == 0)
  1052. break;
  1053. }
  1054. }
  1055. /* It must be already installed, or to be installed */
  1056. number_of_alternatives--;
  1057. if (result && number_of_alternatives == 0) {
  1058. if (root_of_alternatives)
  1059. bb_error_msg_and_die(
  1060. "package %s %sdepends on %s, "
  1061. "which cannot be satisfied",
  1062. name_hashtable[package_node->name],
  1063. package_edge->type == EDGE_PRE_DEPENDS ? "pre-" : "",
  1064. name_hashtable[root_of_alternatives->name]);
  1065. else
  1066. bb_error_msg_and_die(
  1067. "package %s %sdepends on %s, which %s\n",
  1068. name_hashtable[package_node->name],
  1069. package_edge->type == EDGE_PRE_DEPENDS ? "pre-" : "",
  1070. name_hashtable[package_edge->name],
  1071. describe_status(status_num));
  1072. } else if (result == 0 && number_of_alternatives) {
  1073. /* we've found a package which
  1074. * satisfies the dependency,
  1075. * so skip over the rest of
  1076. * the alternatives.
  1077. */
  1078. j += number_of_alternatives;
  1079. number_of_alternatives = 0;
  1080. }
  1081. }
  1082. }
  1083. }
  1084. free(conflicts);
  1085. return TRUE;
  1086. }
  1087. static char **create_list(const char *filename)
  1088. {
  1089. FILE *list_stream;
  1090. char **file_list = NULL;
  1091. char *line = NULL;
  1092. int count = 0;
  1093. /* don't use [xw]fopen here, handle error ourself */
  1094. list_stream = fopen(filename, "r");
  1095. if (list_stream == NULL) {
  1096. return NULL;
  1097. }
  1098. while ((line = xmalloc_getline(list_stream)) != NULL) {
  1099. file_list = xrealloc(file_list, sizeof(char *) * (count + 2));
  1100. file_list[count] = line;
  1101. count++;
  1102. }
  1103. fclose(list_stream);
  1104. if (count == 0) {
  1105. return NULL;
  1106. } else {
  1107. file_list[count] = NULL;
  1108. return file_list;
  1109. }
  1110. }
  1111. /* maybe i should try and hook this into remove_file.c somehow */
  1112. static int remove_file_array(char **remove_names, char **exclude_names)
  1113. {
  1114. struct stat path_stat;
  1115. int match_flag;
  1116. int remove_flag = FALSE;
  1117. int i,j;
  1118. if (remove_names == NULL) {
  1119. return FALSE;
  1120. }
  1121. for (i = 0; remove_names[i] != NULL; i++) {
  1122. match_flag = FALSE;
  1123. if (exclude_names != NULL) {
  1124. for (j = 0; exclude_names[j] != 0; j++) {
  1125. if (strcmp(remove_names[i], exclude_names[j]) == 0) {
  1126. match_flag = TRUE;
  1127. break;
  1128. }
  1129. }
  1130. }
  1131. if (!match_flag) {
  1132. if (lstat(remove_names[i], &path_stat) < 0) {
  1133. continue;
  1134. }
  1135. if (S_ISDIR(path_stat.st_mode)) {
  1136. if (rmdir(remove_names[i]) != -1) {
  1137. remove_flag = TRUE;
  1138. }
  1139. } else {
  1140. if (unlink(remove_names[i]) != -1) {
  1141. remove_flag = TRUE;
  1142. }
  1143. }
  1144. }
  1145. }
  1146. return remove_flag;
  1147. }
  1148. static int run_package_script(const char *package_name, const char *script_type)
  1149. {
  1150. struct stat path_stat;
  1151. char *script_path;
  1152. int result;
  1153. script_path = xasprintf("/var/lib/dpkg/info/%s.%s", package_name, script_type);
  1154. /* If the file doesnt exist is isnt a fatal */
  1155. result = lstat(script_path, &path_stat) < 0 ? EXIT_SUCCESS : system(script_path);
  1156. free(script_path);
  1157. return result;
  1158. }
  1159. static const char *all_control_files[] = {"preinst", "postinst", "prerm", "postrm",
  1160. "list", "md5sums", "shlibs", "conffiles", "config", "templates", NULL };
  1161. static char **all_control_list(const char *package_name)
  1162. {
  1163. unsigned i = 0;
  1164. char **remove_files;
  1165. /* Create a list of all /var/lib/dpkg/info/<package> files */
  1166. remove_files = xzalloc(sizeof(all_control_files));
  1167. while (all_control_files[i]) {
  1168. remove_files[i] = xasprintf("/var/lib/dpkg/info/%s.%s", package_name, all_control_files[i]);
  1169. i++;
  1170. }
  1171. return remove_files;
  1172. }
  1173. static void free_array(char **array)
  1174. {
  1175. if (array) {
  1176. unsigned i = 0;
  1177. while (array[i]) {
  1178. free(array[i]);
  1179. i++;
  1180. }
  1181. free(array);
  1182. }
  1183. }
  1184. /* This function lists information on the installed packages. It loops through
  1185. * the status_hashtable to retrieve the info. This results in smaller code than
  1186. * scanning the status file. The resulting list, however, is unsorted.
  1187. */
  1188. static void list_packages(void)
  1189. {
  1190. int i;
  1191. puts(" Name Version");
  1192. puts("+++-==============-==============");
  1193. /* go through status hash, dereference package hash and finally strings */
  1194. for (i=0; i<STATUS_HASH_PRIME+1; i++) {
  1195. if (status_hashtable[i]) {
  1196. const char *stat_str; /* status string */
  1197. const char *name_str; /* package name */
  1198. const char *vers_str; /* version */
  1199. char s1, s2; /* status abbreviations */
  1200. int spccnt; /* space count */
  1201. int j;
  1202. stat_str = name_hashtable[status_hashtable[i]->status];
  1203. name_str = name_hashtable[package_hashtable[status_hashtable[i]->package]->name];
  1204. vers_str = name_hashtable[package_hashtable[status_hashtable[i]->package]->version];
  1205. /* get abbreviation for status field 1 */
  1206. s1 = stat_str[0] == 'i' ? 'i' : 'r';
  1207. /* get abbreviation for status field 2 */
  1208. for (j=0, spccnt=0; stat_str[j] && spccnt<2; j++) {
  1209. if (stat_str[j] == ' ') spccnt++;
  1210. }
  1211. s2 = stat_str[j];
  1212. /* print out the line formatted like Debian dpkg */
  1213. printf("%c%c %-14s %s\n", s1, s2, name_str, vers_str);
  1214. }
  1215. }
  1216. }
  1217. static void remove_package(const unsigned int package_num, int noisy)
  1218. {
  1219. const char *package_name = name_hashtable[package_hashtable[package_num]->name];
  1220. const char *package_version = name_hashtable[package_hashtable[package_num]->version];
  1221. const unsigned int status_num = search_status_hashtable(package_name);
  1222. const int package_name_length = strlen(package_name);
  1223. char **remove_files;
  1224. char **exclude_files;
  1225. char list_name[package_name_length + 25];
  1226. char conffile_name[package_name_length + 30];
  1227. int return_value;
  1228. if (noisy)
  1229. printf("Removing %s (%s)...\n", package_name, package_version);
  1230. /* run prerm script */
  1231. return_value = run_package_script(package_name, "prerm");
  1232. if (return_value == -1) {
  1233. bb_error_msg_and_die("script failed, prerm failure");
  1234. }
  1235. /* Create a list of files to remove, and a separate list of those to keep */
  1236. sprintf(list_name, "/var/lib/dpkg/info/%s.list", package_name);
  1237. remove_files = create_list(list_name);
  1238. sprintf(conffile_name, "/var/lib/dpkg/info/%s.conffiles", package_name);
  1239. exclude_files = create_list(conffile_name);
  1240. /* Some directories can't be removed straight away, so do multiple passes */
  1241. while (remove_file_array(remove_files, exclude_files)) /*repeat */;
  1242. free_array(exclude_files);
  1243. free_array(remove_files);
  1244. /* Create a list of files in /var/lib/dpkg/info/<package>.* to keep */
  1245. exclude_files = xzalloc(sizeof(char*) * 3);
  1246. exclude_files[0] = xstrdup(conffile_name);
  1247. exclude_files[1] = xasprintf("/var/lib/dpkg/info/%s.postrm", package_name);
  1248. /* Create a list of all /var/lib/dpkg/info/<package> files */
  1249. remove_files = all_control_list(package_name);
  1250. remove_file_array(remove_files, exclude_files);
  1251. free_array(remove_files);
  1252. free_array(exclude_files);
  1253. /* rename <package>.conffile to <package>.list */
  1254. rename(conffile_name, list_name);
  1255. /* Change package status */
  1256. set_status(status_num, "config-files", 3);
  1257. }
  1258. static void purge_package(const unsigned int package_num)
  1259. {
  1260. const char *package_name = name_hashtable[package_hashtable[package_num]->name];
  1261. const char *package_version = name_hashtable[package_hashtable[package_num]->version];
  1262. const unsigned int status_num = search_status_hashtable(package_name);
  1263. char **remove_files;
  1264. char **exclude_files;
  1265. char list_name[strlen(package_name) + 25];
  1266. printf("Purging %s (%s)...\n", package_name, package_version);
  1267. /* run prerm script */
  1268. if (run_package_script(package_name, "prerm") != 0) {
  1269. bb_error_msg_and_die("script failed, prerm failure");
  1270. }
  1271. /* Create a list of files to remove */
  1272. sprintf(list_name, "/var/lib/dpkg/info/%s.list", package_name);
  1273. remove_files = create_list(list_name);
  1274. exclude_files = xzalloc(sizeof(char*));
  1275. /* Some directories cant be removed straight away, so do multiple passes */
  1276. while (remove_file_array(remove_files, exclude_files)) /* repeat */;
  1277. free_array(remove_files);
  1278. /* Create a list of all /var/lib/dpkg/info/<package> files */
  1279. remove_files = all_control_list(package_name);
  1280. remove_file_array(remove_files, exclude_files);
  1281. free_array(remove_files);
  1282. free(exclude_files);
  1283. /* run postrm script */
  1284. if (run_package_script(package_name, "postrm") == -1) {
  1285. bb_error_msg_and_die("postrm fialure.. set status to what?");
  1286. }
  1287. /* Change package status */
  1288. set_status(status_num, "not-installed", 3);
  1289. }
  1290. static archive_handle_t *init_archive_deb_ar(const char *filename)
  1291. {
  1292. archive_handle_t *ar_handle;
  1293. /* Setup an ar archive handle that refers to the gzip sub archive */
  1294. ar_handle = init_handle();
  1295. ar_handle->filter = filter_accept_list_reassign;
  1296. ar_handle->src_fd = xopen(filename, O_RDONLY);
  1297. return ar_handle;
  1298. }
  1299. static void init_archive_deb_control(archive_handle_t *ar_handle)
  1300. {
  1301. archive_handle_t *tar_handle;
  1302. /* Setup the tar archive handle */
  1303. tar_handle = init_handle();
  1304. tar_handle->src_fd = ar_handle->src_fd;
  1305. /* We don't care about data.tar.* or debian-binary, just control.tar.* */
  1306. #ifdef CONFIG_FEATURE_DEB_TAR_GZ
  1307. llist_add_to(&(ar_handle->accept), "control.tar.gz");
  1308. #endif
  1309. #ifdef CONFIG_FEATURE_DEB_TAR_BZ2
  1310. llist_add_to(&(ar_handle->accept), "control.tar.bz2");
  1311. #endif
  1312. /* Assign the tar handle as a subarchive of the ar handle */
  1313. ar_handle->sub_archive = tar_handle;
  1314. return;
  1315. }
  1316. static void init_archive_deb_data(archive_handle_t *ar_handle)
  1317. {
  1318. archive_handle_t *tar_handle;
  1319. /* Setup the tar archive handle */
  1320. tar_handle = init_handle();
  1321. tar_handle->src_fd = ar_handle->src_fd;
  1322. /* We don't care about control.tar.* or debian-binary, just data.tar.* */
  1323. #ifdef CONFIG_FEATURE_DEB_TAR_GZ
  1324. llist_add_to(&(ar_handle->accept), "data.tar.gz");
  1325. #endif
  1326. #ifdef CONFIG_FEATURE_DEB_TAR_BZ2
  1327. llist_add_to(&(ar_handle->accept), "data.tar.bz2");
  1328. #endif
  1329. /* Assign the tar handle as a subarchive of the ar handle */
  1330. ar_handle->sub_archive = tar_handle;
  1331. return;
  1332. }
  1333. static char *deb_extract_control_file_to_buffer(archive_handle_t *ar_handle, llist_t *myaccept)
  1334. {
  1335. ar_handle->sub_archive->action_data = data_extract_to_buffer;
  1336. ar_handle->sub_archive->accept = myaccept;
  1337. ar_handle->sub_archive->filter = filter_accept_list;
  1338. unpack_ar_archive(ar_handle);
  1339. close(ar_handle->src_fd);
  1340. return ar_handle->sub_archive->buffer;
  1341. }
  1342. static void data_extract_all_prefix(archive_handle_t *archive_handle)
  1343. {
  1344. char *name_ptr = archive_handle->file_header->name;
  1345. name_ptr += strspn(name_ptr, "./");
  1346. if (name_ptr[0] != '\0') {
  1347. archive_handle->file_header->name = xasprintf("%s%s", archive_handle->buffer, name_ptr);
  1348. data_extract_all(archive_handle);
  1349. }
  1350. return;
  1351. }
  1352. static void unpack_package(deb_file_t *deb_file)
  1353. {
  1354. const char *package_name = name_hashtable[package_hashtable[deb_file->package]->name];
  1355. const unsigned int status_num = search_status_hashtable(package_name);
  1356. const unsigned int status_package_num = status_hashtable[status_num]->package;
  1357. char *info_prefix;
  1358. char *list_filename;
  1359. archive_handle_t *archive_handle;
  1360. FILE *out_stream;
  1361. llist_t *accept_list = NULL;
  1362. int i = 0;
  1363. /* If existing version, remove it first */
  1364. if (strcmp(name_hashtable[get_status(status_num, 3)], "installed") == 0) {
  1365. /* Package is already installed, remove old version first */
  1366. printf("Preparing to replace %s %s (using %s)...\n", package_name,
  1367. name_hashtable[package_hashtable[status_package_num]->version],
  1368. deb_file->filename);
  1369. remove_package(status_package_num, 0);
  1370. } else {
  1371. printf("Unpacking %s (from %s)...\n", package_name, deb_file->filename);
  1372. }
  1373. /* Extract control.tar.gz to /var/lib/dpkg/info/<package>.filename */
  1374. info_prefix = xasprintf("/var/lib/dpkg/info/%s.", package_name);
  1375. archive_handle = init_archive_deb_ar(deb_file->filename);
  1376. init_archive_deb_control(archive_handle);
  1377. while (all_control_files[i]) {
  1378. char *c = xasprintf("./%s", all_control_files[i]);
  1379. llist_add_to(&accept_list, c);
  1380. i++;
  1381. }
  1382. archive_handle->sub_archive->accept = accept_list;
  1383. archive_handle->sub_archive->filter = filter_accept_list;
  1384. archive_handle->sub_archive->action_data = data_extract_all_prefix;
  1385. archive_handle->sub_archive->buffer = info_prefix;
  1386. archive_handle->sub_archive->flags |= ARCHIVE_EXTRACT_UNCONDITIONAL;
  1387. unpack_ar_archive(archive_handle);
  1388. /* Run the preinst prior to extracting */
  1389. if (run_package_script(package_name, "preinst") != 0) {
  1390. /* when preinst returns exit code != 0 then quit installation process */
  1391. bb_error_msg_and_die("subprocess pre-installation script returned error");
  1392. }
  1393. /* Extract data.tar.gz to the root directory */
  1394. archive_handle = init_archive_deb_ar(deb_file->filename);
  1395. init_archive_deb_data(archive_handle);
  1396. archive_handle->sub_archive->action_data = data_extract_all_prefix;
  1397. archive_handle->sub_archive->buffer = "/";
  1398. archive_handle->sub_archive->flags |= ARCHIVE_EXTRACT_UNCONDITIONAL;
  1399. unpack_ar_archive(archive_handle);
  1400. /* Create the list file */
  1401. list_filename = xasprintf("/var/lib/dpkg/info/%s.list", package_name);
  1402. out_stream = xfopen(list_filename, "w");
  1403. while (archive_handle->sub_archive->passed) {
  1404. /* the leading . has been stripped by data_extract_all_prefix already */
  1405. fputs(archive_handle->sub_archive->passed->data, out_stream);
  1406. fputc('\n', out_stream);
  1407. archive_handle->sub_archive->passed = archive_handle->sub_archive->passed->link;
  1408. }
  1409. fclose(out_stream);
  1410. /* change status */
  1411. set_status(status_num, "install", 1);
  1412. set_status(status_num, "unpacked", 3);
  1413. free(info_prefix);
  1414. free(list_filename);
  1415. }
  1416. static void configure_package(deb_file_t *deb_file)
  1417. {
  1418. const char *package_name = name_hashtable[package_hashtable[deb_file->package]->name];
  1419. const char *package_version = name_hashtable[package_hashtable[deb_file->package]->version];
  1420. const int status_num = search_status_hashtable(package_name);
  1421. printf("Setting up %s (%s)...\n", package_name, package_version);
  1422. /* Run the postinst script */
  1423. if (run_package_script(package_name, "postinst") != 0) {
  1424. /* TODO: handle failure gracefully */
  1425. bb_error_msg_and_die("postrm failure.. set status to what?");
  1426. }
  1427. /* Change status to reflect success */
  1428. set_status(status_num, "install", 1);
  1429. set_status(status_num, "installed", 3);
  1430. }
  1431. int dpkg_main(int argc, char **argv)
  1432. {
  1433. deb_file_t **deb_file = NULL;
  1434. status_node_t *status_node;
  1435. int opt;
  1436. int package_num;
  1437. int dpkg_opt = 0;
  1438. int deb_count = 0;
  1439. int state_status;
  1440. int status_num;
  1441. int i;
  1442. name_hashtable = xzalloc(sizeof(name_hashtable[0]) * (NAME_HASH_PRIME + 1));
  1443. package_hashtable = xzalloc(sizeof(package_hashtable[0]) * (PACKAGE_HASH_PRIME + 1));
  1444. status_hashtable = xzalloc(sizeof(status_hashtable[0]) * (STATUS_HASH_PRIME + 1));
  1445. while ((opt = getopt(argc, argv, "CF:ilPru")) != -1) {
  1446. switch (opt) {
  1447. case 'C': // equivalent to --configure in official dpkg
  1448. dpkg_opt |= dpkg_opt_configure;
  1449. dpkg_opt |= dpkg_opt_package_name;
  1450. break;
  1451. case 'F': // equivalent to --force in official dpkg
  1452. if (strcmp(optarg, "depends") == 0) {
  1453. dpkg_opt |= dpkg_opt_force_ignore_depends;
  1454. }
  1455. break;
  1456. case 'i':
  1457. dpkg_opt |= dpkg_opt_install;
  1458. dpkg_opt |= dpkg_opt_filename;
  1459. break;
  1460. case 'l':
  1461. dpkg_opt |= dpkg_opt_list_installed;
  1462. break;
  1463. case 'P':
  1464. dpkg_opt |= dpkg_opt_purge;
  1465. dpkg_opt |= dpkg_opt_package_name;
  1466. break;
  1467. case 'r':
  1468. dpkg_opt |= dpkg_opt_remove;
  1469. dpkg_opt |= dpkg_opt_package_name;
  1470. break;
  1471. case 'u': /* Equivalent to --unpack in official dpkg */
  1472. dpkg_opt |= dpkg_opt_unpack;
  1473. dpkg_opt |= dpkg_opt_filename;
  1474. break;
  1475. default:
  1476. bb_show_usage();
  1477. }
  1478. }
  1479. /* check for non-option argument if expected */
  1480. if ((dpkg_opt == 0) || ((argc == optind) && !(dpkg_opt && dpkg_opt_list_installed))) {
  1481. bb_show_usage();
  1482. }
  1483. /* puts("(Reading database ... xxxxx files and directories installed.)"); */
  1484. index_status_file("/var/lib/dpkg/status");
  1485. /* if the list action was given print the installed packages and exit */
  1486. if (dpkg_opt & dpkg_opt_list_installed) {
  1487. list_packages();
  1488. return EXIT_SUCCESS;
  1489. }
  1490. /* Read arguments and store relevant info in structs */
  1491. while (optind < argc) {
  1492. /* deb_count = nb_elem - 1 and we need nb_elem + 1 to allocate terminal node [NULL pointer] */
  1493. deb_file = xrealloc(deb_file, sizeof(deb_file_t *) * (deb_count + 2));
  1494. deb_file[deb_count] = (deb_file_t *) xzalloc(sizeof(deb_file_t));
  1495. if (dpkg_opt & dpkg_opt_filename) {
  1496. archive_handle_t *archive_handle;
  1497. llist_t *control_list = NULL;
  1498. /* Extract the control file */
  1499. llist_add_to(&control_list, "./control");
  1500. archive_handle = init_archive_deb_ar(argv[optind]);
  1501. init_archive_deb_control(archive_handle);
  1502. deb_file[deb_count]->control_file = deb_extract_control_file_to_buffer(archive_handle, control_list);
  1503. if (deb_file[deb_count]->control_file == NULL) {
  1504. bb_error_msg_and_die("cannot extract control file");
  1505. }
  1506. deb_file[deb_count]->filename = xstrdup(argv[optind]);
  1507. package_num = fill_package_struct(deb_file[deb_count]->control_file);
  1508. if (package_num == -1) {
  1509. bb_error_msg("invalid control file in %s", argv[optind]);
  1510. optind++;
  1511. continue;
  1512. }
  1513. deb_file[deb_count]->package = (unsigned int) package_num;
  1514. /* Add the package to the status hashtable */
  1515. if ((dpkg_opt & dpkg_opt_unpack) || (dpkg_opt & dpkg_opt_install)) {
  1516. /* Try and find a currently installed version of this package */
  1517. status_num = search_status_hashtable(name_hashtable[package_hashtable[deb_file[deb_count]->package]->name]);
  1518. /* If no previous entry was found initialise a new entry */
  1519. if ((status_hashtable[status_num] == NULL) ||
  1520. (status_hashtable[status_num]->status == 0)) {
  1521. status_node = (status_node_t *) xmalloc(sizeof(status_node_t));
  1522. status_node->package = deb_file[deb_count]->package;
  1523. /* reinstreq isnt changed to "ok" until the package control info
  1524. * is written to the status file*/
  1525. status_node->status = search_name_hashtable("install reinstreq not-installed");
  1526. status_hashtable[status_num] = status_node;
  1527. } else {
  1528. set_status(status_num, "install", 1);
  1529. set_status(status_num, "reinstreq", 2);
  1530. }
  1531. }
  1532. }
  1533. else if (dpkg_opt & dpkg_opt_package_name) {
  1534. deb_file[deb_count]->package = search_package_hashtable(
  1535. search_name_hashtable(argv[optind]),
  1536. search_name_hashtable("ANY"), VER_ANY);
  1537. if (package_hashtable[deb_file[deb_count]->package] == NULL) {
  1538. bb_error_msg_and_die("package %s is uninstalled or unknown", argv[optind]);
  1539. }
  1540. package_num = deb_file[deb_count]->package;
  1541. status_num = search_status_hashtable(name_hashtable[package_hashtable[package_num]->name]);
  1542. state_status = get_status(status_num, 3);
  1543. /* check package status is "installed" */
  1544. if (dpkg_opt & dpkg_opt_remove) {
  1545. if ((strcmp(name_hashtable[state_status], "not-installed") == 0) ||
  1546. (strcmp(name_hashtable[state_status], "config-files") == 0)) {
  1547. bb_error_msg_and_die("%s is already removed", name_hashtable[package_hashtable[package_num]->name]);
  1548. }
  1549. set_status(status_num, "deinstall", 1);
  1550. }
  1551. else if (dpkg_opt & dpkg_opt_purge) {
  1552. /* if package status is "conf-files" then its ok */
  1553. if (strcmp(name_hashtable[state_status], "not-installed") == 0) {
  1554. bb_error_msg_and_die("%s is already purged", name_hashtable[package_hashtable[package_num]->name]);
  1555. }
  1556. set_status(status_num, "purge", 1);
  1557. }
  1558. }
  1559. deb_count++;
  1560. optind++;
  1561. }
  1562. deb_file[deb_count] = NULL;
  1563. /* Check that the deb file arguments are installable */
  1564. if ((dpkg_opt & dpkg_opt_force_ignore_depends) != dpkg_opt_force_ignore_depends) {
  1565. if (!check_deps(deb_file, 0, deb_count)) {
  1566. bb_error_msg_and_die("dependency check failed");
  1567. }
  1568. }
  1569. /* TODO: install or remove packages in the correct dependency order */
  1570. for (i = 0; i < deb_count; i++) {
  1571. /* Remove or purge packages */
  1572. if (dpkg_opt & dpkg_opt_remove) {
  1573. remove_package(deb_file[i]->package, 1);
  1574. }
  1575. else if (dpkg_opt & dpkg_opt_purge) {
  1576. purge_package(deb_file[i]->package);
  1577. }
  1578. else if (dpkg_opt & dpkg_opt_unpack) {
  1579. unpack_package(deb_file[i]);
  1580. }
  1581. else if (dpkg_opt & dpkg_opt_install) {
  1582. unpack_package(deb_file[i]);
  1583. /* package is configured in second pass below */
  1584. }
  1585. else if (dpkg_opt & dpkg_opt_configure) {
  1586. configure_package(deb_file[i]);
  1587. }
  1588. }
  1589. /* configure installed packages */
  1590. if (dpkg_opt & dpkg_opt_install) {
  1591. for (i = 0; i < deb_count; i++)
  1592. configure_package(deb_file[i]);
  1593. }
  1594. write_status_file(deb_file);
  1595. if (ENABLE_FEATURE_CLEAN_UP) {
  1596. for (i = 0; i < deb_count; i++) {
  1597. free(deb_file[i]->control_file);
  1598. free(deb_file[i]->filename);
  1599. free(deb_file[i]);
  1600. }
  1601. free(deb_file);
  1602. for (i = 0; i < NAME_HASH_PRIME; i++) {
  1603. free(name_hashtable[i]);
  1604. }
  1605. for (i = 0; i < PACKAGE_HASH_PRIME; i++) {
  1606. if (package_hashtable[i] != NULL) {
  1607. free_package(package_hashtable[i]);
  1608. }
  1609. }
  1610. for (i = 0; i < STATUS_HASH_PRIME; i++) {
  1611. free(status_hashtable[i]);
  1612. }
  1613. free(status_hashtable);
  1614. free(package_hashtable);
  1615. free(name_hashtable);
  1616. }
  1617. return EXIT_SUCCESS;
  1618. }