Magellan Linux

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

Parent Directory Parent Directory | Revision Log Revision Log


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