Magellan Linux

Annotation of /trunk/mkinitrd-magellan/busybox/archival/dpkg.c

Parent Directory Parent Directory | Revision Log Revision Log


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