1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70#include "libbb.h"
71#include <fnmatch.h>
72#include "bb_archive.h"
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88#define NAME_HASH_PRIME 16381
89
90
91
92
93
94
95
96
97
98#define PACKAGE_HASH_PRIME 10007
99typedef struct edge_s {
100 unsigned operator:4;
101 unsigned type:4;
102 unsigned name:16;
103 unsigned version:16;
104} edge_t;
105
106typedef struct common_node_s {
107 unsigned name:16;
108 unsigned version:16;
109 unsigned num_of_edges:16;
110 edge_t **edge;
111} common_node_t;
112
113
114
115
116#define STATUS_HASH_PRIME 8191
117typedef struct status_node_s {
118 unsigned package:16;
119 unsigned status:16;
120} status_node_t;
121
122
123
124struct globals {
125 char *name_hashtable[NAME_HASH_PRIME + 1];
126 common_node_t *package_hashtable[PACKAGE_HASH_PRIME + 1];
127 status_node_t *status_hashtable[STATUS_HASH_PRIME + 1];
128};
129#define G (*ptr_to_globals)
130#define name_hashtable (G.name_hashtable )
131#define package_hashtable (G.package_hashtable)
132#define status_hashtable (G.status_hashtable )
133#define INIT_G() do { \
134 SET_PTR_TO_GLOBALS(xzalloc(sizeof(G))); \
135} while (0)
136
137
138
139enum edge_type_e {
140 EDGE_NULL = 0,
141 EDGE_PRE_DEPENDS = 1,
142 EDGE_OR_PRE_DEPENDS = 2,
143 EDGE_DEPENDS = 3,
144 EDGE_OR_DEPENDS = 4,
145 EDGE_REPLACES = 5,
146 EDGE_PROVIDES = 7,
147 EDGE_CONFLICTS = 9,
148 EDGE_SUGGESTS = 11,
149 EDGE_RECOMMENDS = 13,
150 EDGE_ENHANCES = 15
151};
152enum operator_e {
153 VER_NULL = 0,
154 VER_EQUAL = 1,
155 VER_LESS = 2,
156 VER_LESS_EQUAL = 3,
157 VER_MORE = 4,
158 VER_MORE_EQUAL = 5,
159 VER_ANY = 6
160};
161
162typedef struct deb_file_s {
163 char *control_file;
164 char *filename;
165 unsigned package:16;
166} deb_file_t;
167
168
169static void make_hash(const char *key, unsigned *start, unsigned *decrement, const int hash_prime)
170{
171 unsigned long hash_num = key[0];
172 int len = strlen(key);
173 int i;
174
175
176
177 for (i = 1; i < len; i++) {
178
179
180
181
182 hash_num += (key[i] + key[i-1]) << ((key[i] * i) % 24);
183 }
184 *start = (unsigned) hash_num % hash_prime;
185 *decrement = (unsigned) 1 + (hash_num % (hash_prime - 1));
186}
187
188
189static int search_name_hashtable(const char *key)
190{
191 unsigned probe_address;
192 unsigned probe_decrement;
193
194 make_hash(key, &probe_address, &probe_decrement, NAME_HASH_PRIME);
195 while (name_hashtable[probe_address] != NULL) {
196 if (strcmp(name_hashtable[probe_address], key) == 0) {
197 return probe_address;
198 }
199 probe_address -= probe_decrement;
200 if ((int)probe_address < 0) {
201 probe_address += NAME_HASH_PRIME;
202 }
203 }
204 name_hashtable[probe_address] = xstrdup(key);
205 return probe_address;
206}
207
208
209
210
211static unsigned search_status_hashtable(const char *key)
212{
213 unsigned probe_address;
214 unsigned probe_decrement;
215
216 make_hash(key, &probe_address, &probe_decrement, STATUS_HASH_PRIME);
217 while (status_hashtable[probe_address] != NULL) {
218 if (strcmp(key, name_hashtable[package_hashtable[status_hashtable[probe_address]->package]->name]) == 0) {
219 break;
220 }
221 probe_address -= probe_decrement;
222 if ((int)probe_address < 0) {
223 probe_address += STATUS_HASH_PRIME;
224 }
225 }
226 return probe_address;
227}
228
229static int order(char x)
230{
231 return (x == '~' ? -1
232 : x == '\0' ? 0
233 : isdigit(x) ? 0
234 : isalpha(x) ? x
235 : (unsigned char)x + 256
236 );
237}
238
239
240static int version_compare_part(const char *val, const char *ref)
241{
242 if (!val) val = "";
243 if (!ref) ref = "";
244
245 while (*val || *ref) {
246 int first_diff;
247
248 while ((*val && !isdigit(*val)) || (*ref && !isdigit(*ref))) {
249 int vc = order(*val);
250 int rc = order(*ref);
251 if (vc != rc)
252 return vc - rc;
253 val++;
254 ref++;
255 }
256
257 while (*val == '0')
258 val++;
259 while (*ref == '0')
260 ref++;
261
262 first_diff = 0;
263 while (isdigit(*val) && isdigit(*ref)) {
264 if (first_diff == 0)
265 first_diff = *val - *ref;
266 val++;
267 ref++;
268 }
269 if (isdigit(*val))
270 return 1;
271 if (isdigit(*ref))
272 return -1;
273 if (first_diff)
274 return first_diff;
275 }
276 return 0;
277}
278
279
280
281
282
283static int version_compare(const unsigned ver1, const unsigned ver2)
284{
285 char *ch_ver1 = name_hashtable[ver1];
286 char *ch_ver2 = name_hashtable[ver2];
287 unsigned epoch1 = 0, epoch2 = 0;
288 char *colon;
289 char *deb_ver1, *deb_ver2;
290 char *upstream_ver1;
291 char *upstream_ver2;
292 int result;
293
294
295 colon = strchr(ch_ver1, ':');
296 if (colon) {
297 epoch1 = atoi(ch_ver1);
298 ch_ver1 = colon + 1;
299 }
300 colon = strchr(ch_ver2, ':');
301 if (colon) {
302 epoch2 = atoi(ch_ver2);
303 ch_ver2 = colon + 1;
304 }
305 if (epoch1 < epoch2) {
306 return -1;
307 }
308 if (epoch1 > epoch2) {
309 return 1;
310 }
311
312
313 upstream_ver1 = xstrdup(ch_ver1);
314 upstream_ver2 = xstrdup(ch_ver2);
315
316
317 deb_ver1 = strrchr(upstream_ver1, '-');
318 deb_ver2 = strrchr(upstream_ver2, '-');
319 if (deb_ver1) {
320 *deb_ver1++ = '\0';
321 }
322 if (deb_ver2) {
323 *deb_ver2++ = '\0';
324 }
325 result = version_compare_part(upstream_ver1, upstream_ver2);
326 if (result == 0) {
327
328 result = version_compare_part(deb_ver1, deb_ver2);
329 }
330
331 free(upstream_ver1);
332 free(upstream_ver2);
333 return result;
334}
335
336static int test_version(const unsigned version1, const unsigned version2, const unsigned operator)
337{
338 const int version_result = version_compare(version1, version2);
339 switch (operator) {
340 case VER_ANY:
341 return TRUE;
342 case VER_EQUAL:
343 return (version_result == 0);
344 case VER_LESS:
345 return (version_result < 0);
346 case VER_LESS_EQUAL:
347 return (version_result <= 0);
348 case VER_MORE:
349 return (version_result > 0);
350 case VER_MORE_EQUAL:
351 return (version_result >= 0);
352 }
353 return FALSE;
354}
355
356static int search_package_hashtable(const unsigned name, const unsigned version, const unsigned operator)
357{
358 unsigned probe_address;
359 unsigned probe_decrement;
360
361 make_hash(name_hashtable[name], &probe_address, &probe_decrement, PACKAGE_HASH_PRIME);
362 while (package_hashtable[probe_address] != NULL) {
363 if (package_hashtable[probe_address]->name == name) {
364 if (operator == VER_ANY) {
365 return probe_address;
366 }
367 if (test_version(package_hashtable[probe_address]->version, version, operator)) {
368 return probe_address;
369 }
370 }
371 probe_address -= probe_decrement;
372 if ((int)probe_address < 0) {
373 probe_address += PACKAGE_HASH_PRIME;
374 }
375 }
376 return probe_address;
377}
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395static int search_for_provides(int needle, int start_at)
396{
397 int i, j;
398 common_node_t *p;
399 for (i = start_at + 1; i < PACKAGE_HASH_PRIME; i++) {
400 p = package_hashtable[i];
401 if (p == NULL)
402 continue;
403 for (j = 0; j < p->num_of_edges; j++)
404 if (p->edge[j]->type == EDGE_PROVIDES && p->edge[j]->name == needle)
405 return i;
406 }
407 return -1;
408}
409
410
411
412
413static void add_edge_to_node(common_node_t *node, edge_t *edge)
414{
415 node->edge = xrealloc_vector(node->edge, 2, node->num_of_edges);
416 node->edge[node->num_of_edges++] = edge;
417}
418
419
420
421
422
423
424
425
426
427
428
429static void add_split_dependencies(common_node_t *parent_node, const char *whole_line, unsigned edge_type)
430{
431 char *line = xstrdup(whole_line);
432 char *line2;
433 char *line_ptr1 = NULL;
434 char *line_ptr2 = NULL;
435 char *field;
436 char *field2;
437 char *version;
438 edge_t *edge;
439 edge_t *or_edge;
440 int offset_ch;
441
442 field = strtok_r(line, ",", &line_ptr1);
443 do {
444
445 field += strspn(field, " ");
446 line2 = xstrdup(field);
447 field2 = strtok_r(line2, "|", &line_ptr2);
448 or_edge = NULL;
449 if ((edge_type == EDGE_DEPENDS || edge_type == EDGE_PRE_DEPENDS)
450 && (strcmp(field, field2) != 0)
451 ) {
452 or_edge = xzalloc(sizeof(edge_t));
453 or_edge->type = edge_type + 1;
454 or_edge->name = search_name_hashtable(field);
455
456 add_edge_to_node(parent_node, or_edge);
457 }
458
459 do {
460 edge = xmalloc(sizeof(edge_t));
461 edge->type = edge_type;
462
463
464 field2 += strspn(field2, " ");
465
466
467 version = strchr(field2, '(');
468 if (version == NULL) {
469 edge->operator = VER_ANY;
470
471 edge->version = search_name_hashtable("ANY");
472 } else {
473
474 version += strspn(version, " (");
475
476 offset_ch = strspn(version, "<=>");
477
478 if (offset_ch > 0) {
479 if (strncmp(version, "=", offset_ch) == 0) {
480 edge->operator = VER_EQUAL;
481 } else if (strncmp(version, "<<", offset_ch) == 0) {
482 edge->operator = VER_LESS;
483 } else if (strncmp(version, "<=", offset_ch) == 0) {
484 edge->operator = VER_LESS_EQUAL;
485 } else if (strncmp(version, ">>", offset_ch) == 0) {
486 edge->operator = VER_MORE;
487 } else if (strncmp(version, ">=", offset_ch) == 0) {
488 edge->operator = VER_MORE_EQUAL;
489 } else {
490 bb_simple_error_msg_and_die("illegal operator");
491 }
492 }
493
494 version += offset_ch;
495 version += strspn(version, " ");
496
497
498 version[strcspn(version, " )")] = '\0';
499
500 edge->version = search_name_hashtable(version);
501 }
502
503
504 field2[strcspn(field2, " (")] = '\0';
505 edge->name = search_name_hashtable(field2);
506
507 if (or_edge)
508 or_edge->version++;
509
510 add_edge_to_node(parent_node, edge);
511 field2 = strtok_r(NULL, "|", &line_ptr2);
512 } while (field2 != NULL);
513
514 free(line2);
515 field = strtok_r(NULL, ",", &line_ptr1);
516 } while (field != NULL);
517
518 free(line);
519}
520
521static void free_package(common_node_t *node)
522{
523 unsigned i;
524 if (node) {
525 for (i = 0; i < node->num_of_edges; i++) {
526 free(node->edge[i]);
527 }
528 free(node->edge);
529 free(node);
530 }
531}
532
533
534
535
536
537static int read_package_field(const char *package_buffer, char **field_name, char **field_value)
538{
539 int offset_name_start = 0;
540 int offset_name_end = 0;
541 int offset_value_start = 0;
542 int offset_value_end = 0;
543 int offset = 0;
544 int next_offset;
545 int name_length;
546 int value_length;
547 int exit_flag = FALSE;
548
549 if (package_buffer == NULL) {
550 *field_name = NULL;
551 *field_value = NULL;
552 return -1;
553 }
554 while (1) {
555 next_offset = offset + 1;
556 switch (package_buffer[offset]) {
557 case '\0':
558 exit_flag = TRUE;
559 break;
560 case ':':
561 if (offset_name_end == 0) {
562 offset_name_end = offset;
563 offset_value_start = next_offset;
564 }
565
566
567 break;
568 case '\n':
569
570 if (package_buffer[next_offset] != ' ') {
571 exit_flag = TRUE;
572 break;
573 }
574 case '\t':
575 case ' ':
576
577 if (offset_name_start == offset) {
578 offset_name_start++;
579 }
580 if (offset_value_start == offset) {
581 offset_value_start++;
582 }
583 break;
584 }
585 if (exit_flag) {
586
587 offset_value_end = offset;
588 name_length = offset_name_end - offset_name_start;
589 value_length = offset_value_end - offset_value_start;
590 if (name_length == 0) {
591 break;
592 }
593 if ((name_length > 0) && (value_length > 0)) {
594 break;
595 }
596
597
598 exit_flag = FALSE;
599 offset_name_start = offset + 1;
600 offset_name_end = 0;
601 offset_value_start = offset + 1;
602 offset_value_end = offset + 1;
603 offset++;
604 }
605 offset++;
606 }
607 *field_name = NULL;
608 if (name_length) {
609 *field_name = xstrndup(&package_buffer[offset_name_start], name_length);
610 }
611 *field_value = NULL;
612 if (value_length > 0) {
613 *field_value = xstrndup(&package_buffer[offset_value_start], value_length);
614 }
615 return next_offset;
616}
617
618static unsigned fill_package_struct(char *control_buffer)
619{
620 static const char field_names[] ALIGN1 =
621 "Package\0""Version\0"
622 "Pre-Depends\0""Depends\0""Replaces\0""Provides\0"
623 "Conflicts\0""Suggests\0""Recommends\0""Enhances\0";
624
625 common_node_t *new_node = xzalloc(sizeof(common_node_t));
626 char *field_name;
627 char *field_value;
628 int field_start = 0;
629 int num = -1;
630 int buffer_length = strlen(control_buffer);
631
632 new_node->version = search_name_hashtable("unknown");
633 while (field_start < buffer_length) {
634 unsigned field_num;
635
636 field_start += read_package_field(&control_buffer[field_start],
637 &field_name, &field_value);
638
639 if (field_name == NULL) {
640 goto fill_package_struct_cleanup;
641 }
642
643 field_num = index_in_strings(field_names, field_name);
644 switch (field_num) {
645 case 0:
646 new_node->name = search_name_hashtable(field_value);
647 break;
648 case 1:
649 new_node->version = search_name_hashtable(field_value);
650 break;
651 case 2:
652 add_split_dependencies(new_node, field_value, EDGE_PRE_DEPENDS);
653 break;
654 case 3:
655 add_split_dependencies(new_node, field_value, EDGE_DEPENDS);
656 break;
657 case 4:
658 add_split_dependencies(new_node, field_value, EDGE_REPLACES);
659 break;
660 case 5:
661 add_split_dependencies(new_node, field_value, EDGE_PROVIDES);
662 break;
663 case 6:
664 add_split_dependencies(new_node, field_value, EDGE_CONFLICTS);
665 break;
666 case 7:
667 add_split_dependencies(new_node, field_value, EDGE_SUGGESTS);
668 break;
669 case 8:
670 add_split_dependencies(new_node, field_value, EDGE_RECOMMENDS);
671 break;
672 case 9:
673 add_split_dependencies(new_node, field_value, EDGE_ENHANCES);
674 break;
675 }
676 fill_package_struct_cleanup:
677 free(field_name);
678 free(field_value);
679 }
680
681 if (new_node->version == search_name_hashtable("unknown")) {
682 free_package(new_node);
683 return -1;
684 }
685 num = search_package_hashtable(new_node->name, new_node->version, VER_EQUAL);
686 free_package(package_hashtable[num]);
687 package_hashtable[num] = new_node;
688 return num;
689}
690
691
692static unsigned get_status(const unsigned status_node, const int num)
693{
694 char *status_string = name_hashtable[status_hashtable[status_node]->status];
695 char *state_sub_string;
696 unsigned state_sub_num;
697 int len;
698 int i;
699
700
701 for (i = 1; i < num; i++) {
702
703 status_string += strcspn(status_string, " ");
704
705 status_string += strspn(status_string, " ");
706 }
707 len = strcspn(status_string, " \n");
708 state_sub_string = xstrndup(status_string, len);
709 state_sub_num = search_name_hashtable(state_sub_string);
710 free(state_sub_string);
711 return state_sub_num;
712}
713
714static void set_status(const unsigned status_node_num, const char *new_value, const int position)
715{
716 const unsigned new_value_num = search_name_hashtable(new_value);
717 unsigned want = get_status(status_node_num, 1);
718 unsigned flag = get_status(status_node_num, 2);
719 unsigned status = get_status(status_node_num, 3);
720 char *new_status;
721
722 switch (position) {
723 case 1:
724 want = new_value_num;
725 break;
726 case 2:
727 flag = new_value_num;
728 break;
729 case 3:
730 status = new_value_num;
731 break;
732 default:
733 bb_simple_error_msg_and_die("DEBUG ONLY: this shouldnt happen");
734 }
735
736 new_status = xasprintf("%s %s %s", name_hashtable[want], name_hashtable[flag], name_hashtable[status]);
737 status_hashtable[status_node_num]->status = search_name_hashtable(new_status);
738 free(new_status);
739}
740
741static const char *describe_status(int status_num)
742{
743 int status_want, status_state;
744 if (status_hashtable[status_num] == NULL || status_hashtable[status_num]->status == 0)
745 return "is not installed or flagged to be installed";
746
747 status_want = get_status(status_num, 1);
748 status_state = get_status(status_num, 3);
749
750 if (status_state == search_name_hashtable("installed")) {
751 if (status_want == search_name_hashtable("install"))
752 return "is installed";
753 if (status_want == search_name_hashtable("deinstall"))
754 return "is marked to be removed";
755 if (status_want == search_name_hashtable("purge"))
756 return "is marked to be purged";
757 }
758 if (status_want == search_name_hashtable("unknown"))
759 return "is in an indeterminate state";
760 if (status_want == search_name_hashtable("install"))
761 return "is marked to be installed";
762
763 return "is not installed or flagged to be installed";
764}
765
766static void index_status_file(const char *filename)
767{
768 FILE *status_file;
769 char *control_buffer;
770 char *status_line;
771 status_node_t *status_node = NULL;
772 unsigned status_num;
773
774 status_file = xfopen_for_read(filename);
775 while ((control_buffer = xmalloc_fgetline_str(status_file, "\n\n")) != NULL) {
776 const unsigned package_num = fill_package_struct(control_buffer);
777 if (package_num != -1) {
778 status_node = xmalloc(sizeof(status_node_t));
779
780 status_line = strstr(control_buffer, "Status:");
781 if (status_line != NULL) {
782 status_line += 7;
783 status_line += strspn(status_line, " \n\t");
784 status_line = xstrndup(status_line, strcspn(status_line, "\n"));
785 status_node->status = search_name_hashtable(status_line);
786 free(status_line);
787 }
788 status_node->package = package_num;
789 status_num = search_status_hashtable(name_hashtable[package_hashtable[status_node->package]->name]);
790 status_hashtable[status_num] = status_node;
791 }
792 free(control_buffer);
793 }
794 fclose(status_file);
795}
796
797static void write_buffer_no_status(FILE *new_status_file, const char *control_buffer)
798{
799 char *name;
800 char *value;
801 int start = 0;
802 while (1) {
803 start += read_package_field(&control_buffer[start], &name, &value);
804 if (name == NULL) {
805 break;
806 }
807 if (strcmp(name, "Status") != 0) {
808 fprintf(new_status_file, "%s: %s\n", name, value);
809 }
810 }
811}
812
813
814static void write_status_file(deb_file_t **deb_file)
815{
816 FILE *old_status_file = xfopen_for_read("/var/lib/dpkg/status");
817 FILE *new_status_file = xfopen_for_write("/var/lib/dpkg/status.udeb");
818 char *package_name;
819 char *status_from_file;
820 char *control_buffer = NULL;
821 char *tmp_string;
822 int status_num;
823 int field_start = 0;
824 int write_flag;
825 int i = 0;
826
827
828 while ((control_buffer = xmalloc_fgetline_str(old_status_file, "\n\n")) != NULL) {
829 tmp_string = strstr(control_buffer, "Package:");
830 if (tmp_string == NULL) {
831 continue;
832 }
833
834 tmp_string += 8;
835 tmp_string += strspn(tmp_string, " \n\t");
836 package_name = xstrndup(tmp_string, strcspn(tmp_string, "\n"));
837 write_flag = FALSE;
838 tmp_string = strstr(control_buffer, "Status:");
839 if (tmp_string != NULL) {
840
841 tmp_string += 7;
842 tmp_string += strspn(tmp_string, " \n\t");
843 status_from_file = xstrndup(tmp_string, strcspn(tmp_string, "\n"));
844 } else {
845 status_from_file = NULL;
846 }
847
848
849 status_num = search_status_hashtable(package_name);
850 if (status_hashtable[status_num] != NULL) {
851 const char *status_from_hashtable = name_hashtable[status_hashtable[status_num]->status];
852 if (strcmp(status_from_file, status_from_hashtable) != 0) {
853
854 const int state_status = get_status(status_num, 3);
855 if ((strcmp("installed", name_hashtable[state_status]) == 0)
856 || (strcmp("unpacked", name_hashtable[state_status]) == 0)
857 ) {
858
859 i = 0;
860 while (deb_file[i] != NULL) {
861 if (strcmp(package_name, name_hashtable[package_hashtable[deb_file[i]->package]->name]) == 0) {
862
863
864 write_buffer_no_status(new_status_file, deb_file[i]->control_file);
865 set_status(status_num, "ok", 2);
866 fprintf(new_status_file, "Status: %s\n\n",
867 name_hashtable[status_hashtable[status_num]->status]);
868 write_flag = TRUE;
869 break;
870 }
871 i++;
872 }
873
874 if (deb_file[i] == NULL) {
875 bb_error_msg_and_die("ALERT: cannot find a control file, "
876 "your status file may be broken, status may be "
877 "incorrect for %s", package_name);
878 }
879 }
880 else if (strcmp("not-installed", name_hashtable[state_status]) == 0) {
881
882 fprintf(new_status_file, "Package: %s\n", package_name);
883 fprintf(new_status_file, "Status: %s\n", status_from_hashtable);
884
885 while (1) {
886 char *field_name;
887 char *field_value;
888 field_start += read_package_field(&control_buffer[field_start], &field_name, &field_value);
889 if (field_name == NULL) {
890 break;
891 }
892 if ((strcmp(field_name, "Priority") == 0)
893 || (strcmp(field_name, "Section") == 0)
894 ) {
895 fprintf(new_status_file, "%s: %s\n", field_name, field_value);
896 }
897 }
898 write_flag = TRUE;
899 fputs("\n", new_status_file);
900 }
901 else if (strcmp("config-files", name_hashtable[state_status]) == 0) {
902
903 while (1) {
904 char *field_name;
905 char *field_value;
906 field_start += read_package_field(&control_buffer[field_start], &field_name, &field_value);
907 if (field_name == NULL) {
908 break;
909 }
910
911 if (strcmp(field_name, "Status") == 0) {
912 fprintf(new_status_file, "Status: %s\n", status_from_hashtable);
913 } else {
914 fprintf(new_status_file, "%s: %s\n", field_name, field_value);
915 }
916 }
917 write_flag = TRUE;
918 fputs("\n", new_status_file);
919 }
920 }
921 }
922
923 if (!write_flag) {
924 fprintf(new_status_file, "%s\n\n", control_buffer);
925 }
926
927 free(status_from_file);
928 free(package_name);
929 free(control_buffer);
930 }
931
932
933 for (i = 0; deb_file[i] != NULL; i++) {
934 status_num = search_status_hashtable(name_hashtable[package_hashtable[deb_file[i]->package]->name]);
935 if (strcmp("reinstreq", name_hashtable[get_status(status_num, 2)]) == 0) {
936 write_buffer_no_status(new_status_file, deb_file[i]->control_file);
937 set_status(status_num, "ok", 2);
938 fprintf(new_status_file, "Status: %s\n\n", name_hashtable[status_hashtable[status_num]->status]);
939 }
940 }
941 fclose(old_status_file);
942 fclose(new_status_file);
943
944
945 if (rename("/var/lib/dpkg/status", "/var/lib/dpkg/status.udeb.bak") == -1) {
946 if (errno != ENOENT)
947 bb_simple_error_msg_and_die("can't create backup status file");
948
949
950 bb_simple_error_msg("no status file found, creating new one");
951 }
952
953 xrename("/var/lib/dpkg/status.udeb", "/var/lib/dpkg/status");
954}
955
956
957
958
959
960
961
962
963static int package_satisfies_dependency(int package, int depend_type)
964{
965 int status_num = search_status_hashtable(name_hashtable[package_hashtable[package]->name]);
966
967
968
969
970 if (status_hashtable[status_num] == NULL)
971 return 0;
972
973 switch (depend_type) {
974 case EDGE_PRE_DEPENDS: return get_status(status_num, 3) == search_name_hashtable("installed");
975 case EDGE_DEPENDS: return get_status(status_num, 1) == search_name_hashtable("install");
976 }
977 return 0;
978}
979
980static int check_deps(deb_file_t **deb_file, int deb_start )
981{
982 int *conflicts = NULL;
983 int conflicts_num = 0;
984 int i = deb_start;
985 int j;
986
987
988
989
990
991
992
993
994
995
996 while (deb_file[i] != NULL) {
997 const unsigned package_num = deb_file[i]->package;
998 conflicts = xrealloc_vector(conflicts, 2, conflicts_num);
999 conflicts[conflicts_num] = package_num;
1000 conflicts_num++;
1001
1002 for (j = 0; j < package_hashtable[package_num]->num_of_edges; j++) {
1003 if (package_hashtable[package_num]->edge[j]->type == EDGE_PROVIDES) {
1004 const int conflicts_package_num = search_package_hashtable(
1005 package_hashtable[package_num]->edge[j]->name,
1006 package_hashtable[package_num]->edge[j]->version,
1007 package_hashtable[package_num]->edge[j]->operator);
1008 if (package_hashtable[conflicts_package_num] == NULL) {
1009
1010 common_node_t *new_node = xzalloc(sizeof(common_node_t));
1011 new_node->name = package_hashtable[package_num]->edge[j]->name;
1012 new_node->version = package_hashtable[package_num]->edge[j]->version;
1013 package_hashtable[conflicts_package_num] = new_node;
1014 }
1015 conflicts = xrealloc_vector(conflicts, 2, conflicts_num);
1016 conflicts[conflicts_num] = conflicts_package_num;
1017 conflicts_num++;
1018 }
1019 }
1020 i++;
1021 }
1022
1023
1024 i = 0;
1025 while (deb_file[i] != NULL) {
1026 const common_node_t *package_node = package_hashtable[deb_file[i]->package];
1027 int status_num = 0;
1028 status_num = search_status_hashtable(name_hashtable[package_node->name]);
1029
1030 if (get_status(status_num, 3) == search_name_hashtable("installed")) {
1031 i++;
1032 continue;
1033 }
1034
1035 for (j = 0; j < package_node->num_of_edges; j++) {
1036 const edge_t *package_edge = package_node->edge[j];
1037
1038 if (package_edge->type == EDGE_CONFLICTS) {
1039 const unsigned package_num =
1040 search_package_hashtable(package_edge->name,
1041 package_edge->version,
1042 package_edge->operator);
1043 int result = 0;
1044 if (package_hashtable[package_num] != NULL) {
1045 status_num = search_status_hashtable(name_hashtable[package_hashtable[package_num]->name]);
1046
1047 if (get_status(status_num, 1) == search_name_hashtable("install")) {
1048 result = test_version(package_hashtable[deb_file[i]->package]->version,
1049 package_edge->version, package_edge->operator);
1050 }
1051 }
1052
1053 if (result) {
1054 bb_error_msg_and_die("package %s conflicts with %s",
1055 name_hashtable[package_node->name],
1056 name_hashtable[package_edge->name]);
1057 }
1058 }
1059 }
1060 i++;
1061 }
1062
1063
1064
1065 for (i = 0; i < PACKAGE_HASH_PRIME; i++) {
1066 int status_num = 0;
1067 int number_of_alternatives = 0;
1068 const edge_t * root_of_alternatives = NULL;
1069 const common_node_t *package_node = package_hashtable[i];
1070
1071
1072
1073
1074
1075 if (package_node == NULL) continue;
1076
1077 status_num = search_status_hashtable(name_hashtable[package_node->name]);
1078
1079
1080
1081
1082
1083 if (status_hashtable[status_num] == NULL) continue;
1084
1085
1086
1087
1088 if (get_status(status_num, 1) != search_name_hashtable("install")) {
1089 continue;
1090 }
1091
1092
1093
1094
1095
1096 for (j = 0; j < package_node->num_of_edges; j++) {
1097 const edge_t *package_edge = package_node->edge[j];
1098 unsigned package_num;
1099
1100 if (package_edge->type == EDGE_OR_PRE_DEPENDS
1101 || package_edge->type == EDGE_OR_DEPENDS
1102 ) {
1103
1104 number_of_alternatives = package_edge->version;
1105 root_of_alternatives = package_edge;
1106 continue;
1107 }
1108 if (number_of_alternatives == 0) {
1109 number_of_alternatives = 1;
1110 root_of_alternatives = NULL;
1111 }
1112
1113 package_num = search_package_hashtable(package_edge->name, package_edge->version, package_edge->operator);
1114
1115 if (package_edge->type == EDGE_PRE_DEPENDS
1116 || package_edge->type == EDGE_DEPENDS
1117 ) {
1118 int result=1;
1119 status_num = 0;
1120
1121
1122
1123
1124
1125
1126
1127 if (root_of_alternatives && package_edge->type != root_of_alternatives->type - 1)
1128 bb_error_msg_and_die("fatal error, package dependencies corrupt: %d != %d - 1",
1129 package_edge->type, root_of_alternatives->type);
1130
1131 if (package_hashtable[package_num] != NULL)
1132 result = !package_satisfies_dependency(package_num, package_edge->type);
1133
1134 if (result) {
1135 int provider = -1;
1136
1137 while ((provider = search_for_provides(package_edge->name, provider)) > -1) {
1138 if (package_hashtable[provider] == NULL) {
1139 puts("Have a provider but no package information for it");
1140 continue;
1141 }
1142 result = !package_satisfies_dependency(provider, package_edge->type);
1143
1144 if (result == 0)
1145 break;
1146 }
1147 }
1148
1149
1150 number_of_alternatives--;
1151 if (result && number_of_alternatives == 0) {
1152 if (root_of_alternatives)
1153 bb_error_msg_and_die(
1154 "package %s %sdepends on %s, which %s",
1155 name_hashtable[package_node->name],
1156 package_edge->type == EDGE_PRE_DEPENDS ? "pre-" : "",
1157 name_hashtable[root_of_alternatives->name],
1158 "cannot be satisfied");
1159 bb_error_msg_and_die(
1160 "package %s %sdepends on %s, which %s",
1161 name_hashtable[package_node->name],
1162 package_edge->type == EDGE_PRE_DEPENDS ? "pre-" : "",
1163 name_hashtable[package_edge->name],
1164 describe_status(status_num));
1165 }
1166 if (result == 0 && number_of_alternatives) {
1167
1168
1169
1170
1171
1172 j += number_of_alternatives;
1173 number_of_alternatives = 0;
1174 }
1175 }
1176 }
1177 }
1178 free(conflicts);
1179 return TRUE;
1180}
1181
1182static char **create_list(const char *filename)
1183{
1184 FILE *list_stream;
1185 char **file_list;
1186 char *line;
1187 int count;
1188
1189
1190 list_stream = fopen_for_read(filename);
1191 if (list_stream == NULL) {
1192 return NULL;
1193 }
1194
1195 file_list = NULL;
1196 count = 0;
1197 while ((line = xmalloc_fgetline(list_stream)) != NULL) {
1198 file_list = xrealloc_vector(file_list, 2, count);
1199 file_list[count++] = line;
1200
1201 }
1202 fclose(list_stream);
1203
1204 return file_list;
1205}
1206
1207
1208
1209
1210
1211static int is_builtin_exclude(const char *name)
1212{
1213 if (*name++ != '/')
1214 return 0;
1215 if (index_in_strings(".\0" "etc\0" "opt\0" "srv\0" "var\0" "var/lib\0",
1216 name) >= 0)
1217 return 1;
1218 if (is_prefixed_with(name, "usr/")) {
1219 name += sizeof("usr/") - 1;
1220 if (is_prefixed_with(name, "local/"))
1221 name += sizeof("local/") - 1;
1222 }
1223
1224 return index_in_strings("bin\0" "lib\0" "lib32\0" "lib64\0" "sbin\0",
1225 name) >= 0;
1226}
1227
1228
1229static int remove_file_array(char **remove_names, char **exclude_names)
1230{
1231 struct stat path_stat;
1232 int remove_flag = 1;
1233 int i, j;
1234
1235 if (remove_names == NULL) {
1236 return 0;
1237 }
1238 for (i = 0; remove_names[i] != NULL; i++) {
1239 if (is_builtin_exclude(remove_names[i]))
1240 continue;
1241 if (exclude_names != NULL) {
1242 for (j = 0; exclude_names[j] != NULL; j++) {
1243 if (strcmp(remove_names[i], exclude_names[j]) == 0) {
1244 goto skip;
1245 }
1246 }
1247 }
1248
1249 if (lstat(remove_names[i], &path_stat) < 0) {
1250 continue;
1251 }
1252 if (S_ISDIR(path_stat.st_mode)) {
1253 remove_flag &= rmdir(remove_names[i]);
1254 } else {
1255 remove_flag &= unlink(remove_names[i]);
1256 }
1257 skip:
1258 continue;
1259 }
1260 return (remove_flag == 0);
1261}
1262
1263static void run_package_script_or_die(const char *package_name, const char *script_type)
1264{
1265 char *script_path;
1266 int result;
1267
1268 script_path = xasprintf("/var/lib/dpkg/info/%s.%s", package_name, script_type);
1269
1270
1271 result = access(script_path, F_OK) ? EXIT_SUCCESS : system(script_path);
1272 free(script_path);
1273 if (result)
1274 bb_error_msg_and_die("%s failed, exit code %d", script_type, result);
1275}
1276
1277
1278
1279
1280
1281
1282
1283
1284
1285
1286
1287
1288
1289
1290
1291
1292
1293
1294
1295
1296
1297
1298
1299
1300
1301
1302
1303
1304
1305
1306
1307static const char *const all_control_files[] ALIGN_PTR = {
1308 "preinst", "postinst", "prerm", "postrm",
1309 "list", "md5sums", "shlibs", "conffiles",
1310 "config", "templates"
1311};
1312
1313static char **all_control_list(const char *package_name)
1314{
1315 unsigned i = 0;
1316 char **remove_files;
1317
1318
1319 remove_files = xzalloc(sizeof(all_control_files) + sizeof(char*));
1320 while (i < ARRAY_SIZE(all_control_files)) {
1321 remove_files[i] = xasprintf("/var/lib/dpkg/info/%s.%s",
1322 package_name, all_control_files[i]);
1323 i++;
1324 }
1325
1326 return remove_files;
1327}
1328
1329static void free_array(char **array)
1330{
1331 if (array) {
1332 unsigned i = 0;
1333 while (array[i]) {
1334 free(array[i]);
1335 i++;
1336 }
1337 free(array);
1338 }
1339}
1340
1341
1342
1343
1344
1345static void list_packages(const char *pattern)
1346{
1347 int i;
1348
1349 puts(" Name Version");
1350 puts("+++-==============-==============");
1351
1352
1353 for (i = 0; i < STATUS_HASH_PRIME+1; i++) {
1354 if (status_hashtable[i]) {
1355 const char *stat_str;
1356 const char *name_str;
1357 const char *vers_str;
1358 char s1, s2;
1359 int spccnt;
1360 int j;
1361
1362 stat_str = name_hashtable[status_hashtable[i]->status];
1363 name_str = name_hashtable[package_hashtable[status_hashtable[i]->package]->name];
1364 vers_str = name_hashtable[package_hashtable[status_hashtable[i]->package]->version];
1365
1366 if (pattern && fnmatch(pattern, name_str, 0) != 0)
1367 continue;
1368
1369
1370 s1 = stat_str[0] == 'i' ? 'i' : 'r';
1371
1372
1373 for (j = 0, spccnt = 0; stat_str[j] && spccnt < 2; j++) {
1374 if (stat_str[j] == ' ') spccnt++;
1375 }
1376 s2 = stat_str[j];
1377
1378
1379 printf("%c%c %-14s %s\n", s1, s2, name_str, vers_str);
1380 }
1381 }
1382}
1383
1384static void remove_package(const unsigned package_num, int noisy)
1385{
1386 const char *package_name = name_hashtable[package_hashtable[package_num]->name];
1387 const char *package_version = name_hashtable[package_hashtable[package_num]->version];
1388 const unsigned status_num = search_status_hashtable(package_name);
1389 const int package_name_length = strlen(package_name);
1390 char **remove_files;
1391 char **exclude_files;
1392 char list_name[package_name_length + 25];
1393 char conffile_name[package_name_length + 30];
1394
1395 if (noisy)
1396 printf("Removing %s (%s)...\n", package_name, package_version);
1397
1398
1399 run_package_script_or_die(package_name, "prerm");
1400
1401
1402 sprintf(list_name, "/var/lib/dpkg/info/%s.%s", package_name, "list");
1403 remove_files = create_list(list_name);
1404
1405 sprintf(conffile_name, "/var/lib/dpkg/info/%s.%s", package_name, "conffiles");
1406 exclude_files = create_list(conffile_name);
1407
1408
1409 while (remove_file_array(remove_files, exclude_files))
1410 continue;
1411 free_array(exclude_files);
1412 free_array(remove_files);
1413
1414
1415 exclude_files = xzalloc(sizeof(exclude_files[0]) * 3);
1416 exclude_files[0] = xstrdup(conffile_name);
1417 exclude_files[1] = xasprintf("/var/lib/dpkg/info/%s.%s", package_name, "postrm");
1418
1419
1420 remove_files = all_control_list(package_name);
1421
1422 remove_file_array(remove_files, exclude_files);
1423 free_array(remove_files);
1424 free_array(exclude_files);
1425
1426
1427
1428
1429 rename(conffile_name, list_name);
1430
1431
1432 set_status(status_num, "config-files", 3);
1433}
1434
1435static void purge_package(const unsigned package_num)
1436{
1437 const char *package_name = name_hashtable[package_hashtable[package_num]->name];
1438 const char *package_version = name_hashtable[package_hashtable[package_num]->version];
1439 const unsigned status_num = search_status_hashtable(package_name);
1440 char **remove_files;
1441 char **exclude_files;
1442 char list_name[strlen(package_name) + 25];
1443
1444 printf("Purging %s (%s)...\n", package_name, package_version);
1445
1446
1447 run_package_script_or_die(package_name, "prerm");
1448
1449
1450 sprintf(list_name, "/var/lib/dpkg/info/%s.%s", package_name, "list");
1451 remove_files = create_list(list_name);
1452
1453
1454 while (remove_file_array(remove_files, NULL))
1455 continue;
1456 free_array(remove_files);
1457
1458
1459 remove_files = all_control_list(package_name);
1460
1461
1462 exclude_files = xzalloc(sizeof(exclude_files[0]) * 2);
1463 exclude_files[0] = xasprintf("/var/lib/dpkg/info/%s.%s", package_name, "postrm");
1464 remove_file_array(remove_files, exclude_files);
1465 free_array(exclude_files);
1466
1467
1468 run_package_script_or_die(package_name, "postrm");
1469 remove_file_array(remove_files, NULL);
1470
1471 free_array(remove_files);
1472
1473
1474 set_status(status_num, "not-installed", 3);
1475}
1476
1477static archive_handle_t *init_archive_deb_ar(const char *filename)
1478{
1479 archive_handle_t *ar_handle;
1480
1481
1482 ar_handle = init_handle();
1483 ar_handle->filter = filter_accept_list_reassign;
1484 ar_handle->src_fd = xopen(filename, O_RDONLY);
1485
1486 return ar_handle;
1487}
1488
1489static void init_archive_deb_control(archive_handle_t *ar_handle)
1490{
1491 archive_handle_t *tar_handle;
1492
1493
1494 tar_handle = init_handle();
1495 tar_handle->src_fd = ar_handle->src_fd;
1496
1497
1498 llist_add_to(&(ar_handle->accept), (char*)"control.tar");
1499#if ENABLE_FEATURE_SEAMLESS_GZ
1500 llist_add_to(&(ar_handle->accept), (char*)"control.tar.gz");
1501#endif
1502#if ENABLE_FEATURE_SEAMLESS_BZ2
1503 llist_add_to(&(ar_handle->accept), (char*)"control.tar.bz2");
1504#endif
1505#if ENABLE_FEATURE_SEAMLESS_XZ
1506 llist_add_to(&(ar_handle->accept), (char*)"control.tar.xz");
1507#endif
1508
1509
1510 ar_handle->dpkg__sub_archive = tar_handle;
1511}
1512
1513static void init_archive_deb_data(archive_handle_t *ar_handle)
1514{
1515 archive_handle_t *tar_handle;
1516
1517
1518 tar_handle = init_handle();
1519 tar_handle->src_fd = ar_handle->src_fd;
1520
1521
1522 llist_add_to(&(ar_handle->accept), (char*)"data.tar");
1523#if ENABLE_FEATURE_SEAMLESS_GZ
1524 llist_add_to(&(ar_handle->accept), (char*)"data.tar.gz");
1525#endif
1526#if ENABLE_FEATURE_SEAMLESS_BZ2
1527 llist_add_to(&(ar_handle->accept), (char*)"data.tar.bz2");
1528#endif
1529#if ENABLE_FEATURE_SEAMLESS_LZMA
1530 llist_add_to(&(ar_handle->accept), (char*)"data.tar.lzma");
1531#endif
1532#if ENABLE_FEATURE_SEAMLESS_XZ
1533 llist_add_to(&(ar_handle->accept), (char*)"data.tar.xz");
1534#endif
1535
1536
1537 ar_handle->dpkg__sub_archive = tar_handle;
1538}
1539
1540static void FAST_FUNC data_extract_to_buffer(archive_handle_t *archive_handle)
1541{
1542 unsigned size = archive_handle->file_header->size;
1543
1544 archive_handle->dpkg__buffer = xzalloc(size + 1);
1545 xread(archive_handle->src_fd, archive_handle->dpkg__buffer, size);
1546}
1547
1548static char *deb_extract_control_file_to_buffer(archive_handle_t *ar_handle, llist_t *myaccept)
1549{
1550 ar_handle->dpkg__sub_archive->action_data = data_extract_to_buffer;
1551 ar_handle->dpkg__sub_archive->accept = myaccept;
1552 ar_handle->dpkg__sub_archive->filter = filter_accept_list;
1553
1554 unpack_ar_archive(ar_handle);
1555 close(ar_handle->src_fd);
1556
1557 return ar_handle->dpkg__sub_archive->dpkg__buffer;
1558}
1559
1560static void append_control_file_to_llist(const char *package_name, const char *control_name, llist_t **ll)
1561{
1562 FILE *fp;
1563 char *filename, *line;
1564
1565 filename = xasprintf("/var/lib/dpkg/info/%s.%s", package_name, control_name);
1566 fp = fopen_for_read(filename);
1567 free(filename);
1568 if (fp != NULL) {
1569 while ((line = xmalloc_fgetline(fp)) != NULL)
1570 llist_add_to(ll, line);
1571 fclose(fp);
1572 }
1573}
1574
1575static char FAST_FUNC filter_rename_config(archive_handle_t *archive_handle)
1576{
1577 int fd;
1578 char *name_ptr = archive_handle->file_header->name + 1;
1579
1580
1581 if (!find_list_entry(archive_handle->accept, name_ptr))
1582 return EXIT_SUCCESS;
1583
1584 fd = open(name_ptr, O_RDONLY);
1585 if (fd >= 0) {
1586 md5_ctx_t md5;
1587 char *md5line, *buf;
1588 int count;
1589
1590
1591 buf = xmalloc(4096);
1592 md5_begin(&md5);
1593 while ((count = safe_read(fd, buf, 4096)) > 0)
1594 md5_hash(&md5, buf, count);
1595 md5_end(&md5, buf);
1596 close(fd);
1597
1598 md5line = xmalloc(16 * 2 + 2 + strlen(name_ptr) + 1);
1599 sprintf(bin2hex(md5line, buf, 16), " %s", name_ptr);
1600 free(buf);
1601
1602
1603 if (find_list_entry(archive_handle->accept, md5line) == NULL) {
1604 printf("Warning: Creating %s as %s.dpkg-new\n", name_ptr, name_ptr);
1605 archive_handle->file_header->name = xasprintf("%s.dpkg-new", archive_handle->file_header->name);
1606 }
1607 free(md5line);
1608 }
1609 return EXIT_SUCCESS;
1610}
1611
1612static void FAST_FUNC data_extract_all_prefix(archive_handle_t *archive_handle)
1613{
1614 char *name_ptr = archive_handle->file_header->name;
1615
1616
1617 while (*name_ptr == '/')
1618 name_ptr++;
1619
1620 while (name_ptr[0] == '.') {
1621 if (name_ptr[1] == '.')
1622 name_ptr++;
1623 if (name_ptr[1] != '/')
1624 break;
1625 name_ptr += 2;
1626 }
1627
1628 if (name_ptr[0] != '\0') {
1629 archive_handle->file_header->name = xasprintf("%s%s", archive_handle->dpkg__buffer, name_ptr);
1630 data_extract_all(archive_handle);
1631 if (fnmatch("*.dpkg-new", archive_handle->file_header->name, 0) == 0) {
1632
1633 archive_handle->file_header->name[strlen(archive_handle->file_header->name) - 9] = '\0';
1634 }
1635 }
1636}
1637
1638enum {
1639
1640 OPT_configure = (1 << 0),
1641 OPT_install = (1 << 1),
1642 OPT_list_installed = (1 << 2),
1643 OPT_purge = (1 << 3),
1644 OPT_remove = (1 << 4),
1645 OPT_unpack = (1 << 5),
1646 OPTMASK_cmd = (1 << 6) - 1,
1647
1648 OPT_force = (1 << 6),
1649 OPT_force_ignore_depends = (1 << 7),
1650 OPT_force_confnew = (1 << 8),
1651 OPT_force_confold = (1 << 9),
1652};
1653
1654static void unpack_package(deb_file_t *deb_file)
1655{
1656 const char *package_name = name_hashtable[package_hashtable[deb_file->package]->name];
1657 const unsigned status_num = search_status_hashtable(package_name);
1658 const unsigned status_package_num = status_hashtable[status_num]->package;
1659 char *info_prefix;
1660 char *list_filename;
1661 archive_handle_t *archive_handle;
1662 FILE *out_stream;
1663 llist_t *accept_list;
1664 llist_t *conffile_list;
1665 int i;
1666
1667
1668 conffile_list = NULL;
1669 if (strcmp(name_hashtable[get_status(status_num, 3)], "installed") == 0) {
1670
1671 printf("Preparing to replace %s %s (using %s)...\n", package_name,
1672 name_hashtable[package_hashtable[status_package_num]->version],
1673 deb_file->filename);
1674
1675
1676 if (!(option_mask32 & OPT_force_confold))
1677 append_control_file_to_llist(package_name, "md5sums", &conffile_list);
1678
1679 remove_package(status_package_num, 0);
1680 } else {
1681 printf("Unpacking %s (from %s)...\n", package_name, deb_file->filename);
1682 }
1683
1684
1685 info_prefix = xasprintf("/var/lib/dpkg/info/%s.%s", package_name, "");
1686 archive_handle = init_archive_deb_ar(deb_file->filename);
1687 init_archive_deb_control(archive_handle);
1688
1689 accept_list = NULL;
1690 i = 0;
1691 while (i < ARRAY_SIZE(all_control_files)) {
1692 char *c = xasprintf("./%s", all_control_files[i]);
1693 llist_add_to(&accept_list, c);
1694 i++;
1695 }
1696 archive_handle->dpkg__sub_archive->accept = accept_list;
1697 archive_handle->dpkg__sub_archive->filter = filter_accept_list;
1698 archive_handle->dpkg__sub_archive->action_data = data_extract_all_prefix;
1699 archive_handle->dpkg__sub_archive->dpkg__buffer = info_prefix;
1700 archive_handle->dpkg__sub_archive->ah_flags |= ARCHIVE_UNLINK_OLD;
1701 unpack_ar_archive(archive_handle);
1702
1703
1704 run_package_script_or_die(package_name, "preinst");
1705
1706
1707 if (!(option_mask32 & OPT_force_confnew))
1708 append_control_file_to_llist(package_name, "conffiles", &conffile_list);
1709
1710
1711 archive_handle = init_archive_deb_ar(deb_file->filename);
1712 init_archive_deb_data(archive_handle);
1713 archive_handle->dpkg__sub_archive->accept = conffile_list;
1714
1715
1716
1717
1718 archive_handle->dpkg__sub_archive->ah_flags |= ARCHIVE_REMEMBER_NAMES | ARCHIVE_UNLINK_OLD;
1719 archive_handle->dpkg__sub_archive->filter = filter_rename_config;
1720 archive_handle->dpkg__sub_archive->action_data = data_extract_all_prefix;
1721 archive_handle->dpkg__sub_archive->dpkg__buffer = (char*)"/";
1722 unpack_ar_archive(archive_handle);
1723
1724
1725 list_filename = xasprintf("/var/lib/dpkg/info/%s.%s", package_name, "list");
1726 out_stream = xfopen_for_write(list_filename);
1727 archive_handle->dpkg__sub_archive->passed = llist_rev(archive_handle->dpkg__sub_archive->passed);
1728 while (archive_handle->dpkg__sub_archive->passed) {
1729 char *filename = llist_pop(&archive_handle->dpkg__sub_archive->passed);
1730
1731 fprintf(out_stream, "%s\n", filename);
1732 free(filename);
1733 }
1734 fclose(out_stream);
1735
1736
1737 set_status(status_num, "install", 1);
1738 set_status(status_num, "unpacked", 3);
1739
1740 free(info_prefix);
1741 free(list_filename);
1742}
1743
1744static void configure_package(deb_file_t *deb_file)
1745{
1746 const char *package_name = name_hashtable[package_hashtable[deb_file->package]->name];
1747 const char *package_version = name_hashtable[package_hashtable[deb_file->package]->version];
1748 const int status_num = search_status_hashtable(package_name);
1749
1750 printf("Setting up %s (%s)...\n", package_name, package_version);
1751
1752
1753
1754 run_package_script_or_die(package_name, "postinst");
1755
1756
1757 set_status(status_num, "install", 1);
1758 set_status(status_num, "installed", 3);
1759}
1760
1761int dpkg_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE;
1762int dpkg_main(int argc UNUSED_PARAM, char **argv)
1763{
1764 deb_file_t **deb_file = NULL;
1765 status_node_t *status_node;
1766 char *str_f;
1767 int opt;
1768 int package_num;
1769 int deb_count = 0;
1770 int state_status;
1771 int status_num;
1772 int i;
1773#if ENABLE_LONG_OPTS
1774 static const char dpkg_longopts[] ALIGN1 =
1775
1776
1777 "configure\0" No_argument "C"
1778 "force\0" Required_argument "F"
1779 "install\0" No_argument "i"
1780 "list\0" No_argument "l"
1781 "purge\0" No_argument "P"
1782 "remove\0" No_argument "r"
1783 "unpack\0" No_argument "u"
1784 "force-depends\0" No_argument "\xff"
1785 "force-confnew\0" No_argument "\xfe"
1786 "force-confold\0" No_argument "\xfd"
1787 ;
1788#endif
1789
1790 INIT_G();
1791
1792 opt = getopt32long(argv, "CilPruF:", dpkg_longopts, &str_f);
1793 argv += optind;
1794
1795 if (opt & OPT_force) {
1796 if (strcmp(str_f, "depends") == 0)
1797 opt |= OPT_force_ignore_depends;
1798 else if (strcmp(str_f, "confnew") == 0)
1799 opt |= OPT_force_confnew;
1800 else if (strcmp(str_f, "confold") == 0)
1801 opt |= OPT_force_confold;
1802 else
1803 bb_show_usage();
1804 option_mask32 = opt;
1805 }
1806
1807
1808
1809
1810
1811 if (!(opt & OPTMASK_cmd)
1812 || ((opt & OPTMASK_cmd) & ((opt & OPTMASK_cmd)-1))
1813 ) {
1814 bb_show_usage();
1815 }
1816
1817
1818 index_status_file("/var/lib/dpkg/status");
1819
1820
1821 if (opt & OPT_list_installed) {
1822 list_packages(argv[0]);
1823 return EXIT_SUCCESS;
1824 }
1825
1826
1827 while (*argv) {
1828
1829 deb_file = xrealloc_vector(deb_file, 2, deb_count);
1830 deb_file[deb_count] = xzalloc(sizeof(deb_file[0][0]));
1831 if (opt & (OPT_install | OPT_unpack)) {
1832
1833 archive_handle_t *archive_handle;
1834 llist_t *control_list = NULL;
1835
1836
1837 llist_add_to(&control_list, (char*)"./control");
1838 archive_handle = init_archive_deb_ar(argv[0]);
1839 init_archive_deb_control(archive_handle);
1840 deb_file[deb_count]->control_file = deb_extract_control_file_to_buffer(archive_handle, control_list);
1841 if (deb_file[deb_count]->control_file == NULL) {
1842 bb_simple_error_msg_and_die("can't extract control file");
1843 }
1844 deb_file[deb_count]->filename = xstrdup(argv[0]);
1845 package_num = fill_package_struct(deb_file[deb_count]->control_file);
1846
1847 if (package_num == -1) {
1848 bb_error_msg("invalid control file in %s", argv[0]);
1849 argv++;
1850 continue;
1851 }
1852 deb_file[deb_count]->package = (unsigned) package_num;
1853
1854
1855 if (opt & (OPT_unpack | OPT_install)) {
1856
1857 status_num = search_status_hashtable(name_hashtable[package_hashtable[deb_file[deb_count]->package]->name]);
1858
1859 if (status_hashtable[status_num] == NULL
1860 || status_hashtable[status_num]->status == 0
1861 ) {
1862 status_node = xmalloc(sizeof(status_node_t));
1863 status_node->package = deb_file[deb_count]->package;
1864
1865
1866 status_node->status = search_name_hashtable("install reinstreq not-installed");
1867 status_hashtable[status_num] = status_node;
1868 } else {
1869 set_status(status_num, "install", 1);
1870 set_status(status_num, "reinstreq", 2);
1871 }
1872 }
1873 } else if (opt & (OPT_configure | OPT_purge | OPT_remove)) {
1874
1875 deb_file[deb_count]->package = search_package_hashtable(
1876 search_name_hashtable(argv[0]),
1877 search_name_hashtable("ANY"), VER_ANY);
1878 if (package_hashtable[deb_file[deb_count]->package] == NULL) {
1879 bb_error_msg_and_die("package %s is uninstalled or unknown", argv[0]);
1880 }
1881 package_num = deb_file[deb_count]->package;
1882 status_num = search_status_hashtable(name_hashtable[package_hashtable[package_num]->name]);
1883 state_status = get_status(status_num, 3);
1884
1885
1886 if (opt & OPT_remove) {
1887 if (strcmp(name_hashtable[state_status], "not-installed") == 0
1888 || strcmp(name_hashtable[state_status], "config-files") == 0
1889 ) {
1890 bb_error_msg_and_die("%s is already removed", name_hashtable[package_hashtable[package_num]->name]);
1891 }
1892 set_status(status_num, "deinstall", 1);
1893 } else if (opt & OPT_purge) {
1894
1895 if (strcmp(name_hashtable[state_status], "not-installed") == 0) {
1896 bb_error_msg_and_die("%s is already purged", name_hashtable[package_hashtable[package_num]->name]);
1897 }
1898 set_status(status_num, "purge", 1);
1899 }
1900 }
1901 deb_count++;
1902 argv++;
1903 }
1904 if (!deb_count)
1905 bb_simple_error_msg_and_die("no package files specified");
1906 deb_file[deb_count] = NULL;
1907
1908
1909 if (!(opt & OPT_force_ignore_depends)) {
1910 if (!check_deps(deb_file, 0 )) {
1911 bb_simple_error_msg_and_die("dependency check failed");
1912 }
1913 }
1914
1915
1916 for (i = 0; i < deb_count; i++) {
1917
1918 if (opt & OPT_remove) {
1919 remove_package(deb_file[i]->package, 1);
1920 }
1921 else if (opt & OPT_purge) {
1922 purge_package(deb_file[i]->package);
1923 }
1924 else if (opt & OPT_unpack) {
1925 unpack_package(deb_file[i]);
1926 }
1927 else if (opt & OPT_install) {
1928 unpack_package(deb_file[i]);
1929
1930 }
1931 else if (opt & OPT_configure) {
1932 configure_package(deb_file[i]);
1933 }
1934 }
1935
1936 if (opt & OPT_install) {
1937 for (i = 0; i < deb_count; i++)
1938 configure_package(deb_file[i]);
1939 }
1940
1941 write_status_file(deb_file);
1942
1943 if (ENABLE_FEATURE_CLEAN_UP) {
1944 for (i = 0; i < deb_count; i++) {
1945 free(deb_file[i]->control_file);
1946 free(deb_file[i]->filename);
1947 free(deb_file[i]);
1948 }
1949
1950 free(deb_file);
1951
1952 for (i = 0; i < NAME_HASH_PRIME; i++) {
1953 free(name_hashtable[i]);
1954 }
1955
1956 for (i = 0; i < PACKAGE_HASH_PRIME; i++) {
1957 free_package(package_hashtable[i]);
1958 }
1959
1960 for (i = 0; i < STATUS_HASH_PRIME; i++) {
1961 free(status_hashtable[i]);
1962 }
1963 }
1964
1965 return EXIT_SUCCESS;
1966}
1967