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_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_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_error_msg_and_die("can't create backup status file");
948
949
950 bb_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
1208static int remove_file_array(char **remove_names, char **exclude_names)
1209{
1210 struct stat path_stat;
1211 int remove_flag = 1;
1212 int i, j;
1213
1214 if (remove_names == NULL) {
1215 return 0;
1216 }
1217 for (i = 0; remove_names[i] != NULL; i++) {
1218 if (exclude_names != NULL) {
1219 for (j = 0; exclude_names[j] != NULL; j++) {
1220 if (strcmp(remove_names[i], exclude_names[j]) == 0) {
1221 goto skip;
1222 }
1223 }
1224 }
1225
1226 if (lstat(remove_names[i], &path_stat) < 0) {
1227 continue;
1228 }
1229 if (S_ISDIR(path_stat.st_mode)) {
1230 remove_flag &= rmdir(remove_names[i]);
1231 } else {
1232 remove_flag &= unlink(remove_names[i]);
1233 }
1234 skip:
1235 continue;
1236 }
1237 return (remove_flag == 0);
1238}
1239
1240static void run_package_script_or_die(const char *package_name, const char *script_type)
1241{
1242 char *script_path;
1243 int result;
1244
1245 script_path = xasprintf("/var/lib/dpkg/info/%s.%s", package_name, script_type);
1246
1247
1248 result = access(script_path, F_OK) ? EXIT_SUCCESS : system(script_path);
1249 free(script_path);
1250 if (result)
1251 bb_error_msg_and_die("%s failed, exit code %d", script_type, result);
1252}
1253
1254
1255
1256
1257
1258
1259
1260
1261
1262
1263
1264
1265
1266
1267
1268
1269
1270
1271
1272
1273
1274
1275
1276
1277
1278
1279
1280
1281
1282
1283
1284static const char *const all_control_files[] = {
1285 "preinst", "postinst", "prerm", "postrm",
1286 "list", "md5sums", "shlibs", "conffiles",
1287 "config", "templates"
1288};
1289
1290static char **all_control_list(const char *package_name)
1291{
1292 unsigned i = 0;
1293 char **remove_files;
1294
1295
1296 remove_files = xzalloc(sizeof(all_control_files) + sizeof(char*));
1297 while (i < ARRAY_SIZE(all_control_files)) {
1298 remove_files[i] = xasprintf("/var/lib/dpkg/info/%s.%s",
1299 package_name, all_control_files[i]);
1300 i++;
1301 }
1302
1303 return remove_files;
1304}
1305
1306static void free_array(char **array)
1307{
1308 if (array) {
1309 unsigned i = 0;
1310 while (array[i]) {
1311 free(array[i]);
1312 i++;
1313 }
1314 free(array);
1315 }
1316}
1317
1318
1319
1320
1321
1322static void list_packages(const char *pattern)
1323{
1324 int i;
1325
1326 puts(" Name Version");
1327 puts("+++-==============-==============");
1328
1329
1330 for (i = 0; i < STATUS_HASH_PRIME+1; i++) {
1331 if (status_hashtable[i]) {
1332 const char *stat_str;
1333 const char *name_str;
1334 const char *vers_str;
1335 char s1, s2;
1336 int spccnt;
1337 int j;
1338
1339 stat_str = name_hashtable[status_hashtable[i]->status];
1340 name_str = name_hashtable[package_hashtable[status_hashtable[i]->package]->name];
1341 vers_str = name_hashtable[package_hashtable[status_hashtable[i]->package]->version];
1342
1343 if (pattern && fnmatch(pattern, name_str, 0) != 0)
1344 continue;
1345
1346
1347 s1 = stat_str[0] == 'i' ? 'i' : 'r';
1348
1349
1350 for (j = 0, spccnt = 0; stat_str[j] && spccnt < 2; j++) {
1351 if (stat_str[j] == ' ') spccnt++;
1352 }
1353 s2 = stat_str[j];
1354
1355
1356 printf("%c%c %-14s %s\n", s1, s2, name_str, vers_str);
1357 }
1358 }
1359}
1360
1361static void remove_package(const unsigned package_num, int noisy)
1362{
1363 const char *package_name = name_hashtable[package_hashtable[package_num]->name];
1364 const char *package_version = name_hashtable[package_hashtable[package_num]->version];
1365 const unsigned status_num = search_status_hashtable(package_name);
1366 const int package_name_length = strlen(package_name);
1367 char **remove_files;
1368 char **exclude_files;
1369 char list_name[package_name_length + 25];
1370 char conffile_name[package_name_length + 30];
1371
1372 if (noisy)
1373 printf("Removing %s (%s)...\n", package_name, package_version);
1374
1375
1376 run_package_script_or_die(package_name, "prerm");
1377
1378
1379 sprintf(list_name, "/var/lib/dpkg/info/%s.%s", package_name, "list");
1380 remove_files = create_list(list_name);
1381
1382 sprintf(conffile_name, "/var/lib/dpkg/info/%s.%s", package_name, "conffiles");
1383 exclude_files = create_list(conffile_name);
1384
1385
1386 while (remove_file_array(remove_files, exclude_files))
1387 continue;
1388 free_array(exclude_files);
1389 free_array(remove_files);
1390
1391
1392 exclude_files = xzalloc(sizeof(exclude_files[0]) * 3);
1393 exclude_files[0] = xstrdup(conffile_name);
1394 exclude_files[1] = xasprintf("/var/lib/dpkg/info/%s.%s", package_name, "postrm");
1395
1396
1397 remove_files = all_control_list(package_name);
1398
1399 remove_file_array(remove_files, exclude_files);
1400 free_array(remove_files);
1401 free_array(exclude_files);
1402
1403
1404
1405
1406 rename(conffile_name, list_name);
1407
1408
1409 set_status(status_num, "config-files", 3);
1410}
1411
1412static void purge_package(const unsigned package_num)
1413{
1414 const char *package_name = name_hashtable[package_hashtable[package_num]->name];
1415 const char *package_version = name_hashtable[package_hashtable[package_num]->version];
1416 const unsigned status_num = search_status_hashtable(package_name);
1417 char **remove_files;
1418 char **exclude_files;
1419 char list_name[strlen(package_name) + 25];
1420
1421 printf("Purging %s (%s)...\n", package_name, package_version);
1422
1423
1424 run_package_script_or_die(package_name, "prerm");
1425
1426
1427 sprintf(list_name, "/var/lib/dpkg/info/%s.%s", package_name, "list");
1428 remove_files = create_list(list_name);
1429
1430
1431 while (remove_file_array(remove_files, NULL))
1432 continue;
1433 free_array(remove_files);
1434
1435
1436 remove_files = all_control_list(package_name);
1437
1438
1439 exclude_files = xzalloc(sizeof(exclude_files[0]) * 2);
1440 exclude_files[0] = xasprintf("/var/lib/dpkg/info/%s.%s", package_name, "postrm");
1441 remove_file_array(remove_files, exclude_files);
1442 free_array(exclude_files);
1443
1444
1445 run_package_script_or_die(package_name, "postrm");
1446 remove_file_array(remove_files, NULL);
1447
1448 free_array(remove_files);
1449
1450
1451 set_status(status_num, "not-installed", 3);
1452}
1453
1454static archive_handle_t *init_archive_deb_ar(const char *filename)
1455{
1456 archive_handle_t *ar_handle;
1457
1458
1459 ar_handle = init_handle();
1460 ar_handle->filter = filter_accept_list_reassign;
1461 ar_handle->src_fd = xopen(filename, O_RDONLY);
1462
1463 return ar_handle;
1464}
1465
1466static void init_archive_deb_control(archive_handle_t *ar_handle)
1467{
1468 archive_handle_t *tar_handle;
1469
1470
1471 tar_handle = init_handle();
1472 tar_handle->src_fd = ar_handle->src_fd;
1473
1474
1475 llist_add_to(&(ar_handle->accept), (char*)"control.tar");
1476#if ENABLE_FEATURE_SEAMLESS_GZ
1477 llist_add_to(&(ar_handle->accept), (char*)"control.tar.gz");
1478#endif
1479#if ENABLE_FEATURE_SEAMLESS_BZ2
1480 llist_add_to(&(ar_handle->accept), (char*)"control.tar.bz2");
1481#endif
1482#if ENABLE_FEATURE_SEAMLESS_XZ
1483 llist_add_to(&(ar_handle->accept), (char*)"control.tar.xz");
1484#endif
1485
1486
1487 ar_handle->dpkg__sub_archive = tar_handle;
1488}
1489
1490static void init_archive_deb_data(archive_handle_t *ar_handle)
1491{
1492 archive_handle_t *tar_handle;
1493
1494
1495 tar_handle = init_handle();
1496 tar_handle->src_fd = ar_handle->src_fd;
1497
1498
1499 llist_add_to(&(ar_handle->accept), (char*)"data.tar");
1500#if ENABLE_FEATURE_SEAMLESS_GZ
1501 llist_add_to(&(ar_handle->accept), (char*)"data.tar.gz");
1502#endif
1503#if ENABLE_FEATURE_SEAMLESS_BZ2
1504 llist_add_to(&(ar_handle->accept), (char*)"data.tar.bz2");
1505#endif
1506#if ENABLE_FEATURE_SEAMLESS_LZMA
1507 llist_add_to(&(ar_handle->accept), (char*)"data.tar.lzma");
1508#endif
1509#if ENABLE_FEATURE_SEAMLESS_XZ
1510 llist_add_to(&(ar_handle->accept), (char*)"data.tar.xz");
1511#endif
1512
1513
1514 ar_handle->dpkg__sub_archive = tar_handle;
1515}
1516
1517static void FAST_FUNC data_extract_to_buffer(archive_handle_t *archive_handle)
1518{
1519 unsigned size = archive_handle->file_header->size;
1520
1521 archive_handle->dpkg__buffer = xzalloc(size + 1);
1522 xread(archive_handle->src_fd, archive_handle->dpkg__buffer, size);
1523}
1524
1525static char *deb_extract_control_file_to_buffer(archive_handle_t *ar_handle, llist_t *myaccept)
1526{
1527 ar_handle->dpkg__sub_archive->action_data = data_extract_to_buffer;
1528 ar_handle->dpkg__sub_archive->accept = myaccept;
1529 ar_handle->dpkg__sub_archive->filter = filter_accept_list;
1530
1531 unpack_ar_archive(ar_handle);
1532 close(ar_handle->src_fd);
1533
1534 return ar_handle->dpkg__sub_archive->dpkg__buffer;
1535}
1536
1537static void append_control_file_to_llist(const char *package_name, const char *control_name, llist_t **ll)
1538{
1539 FILE *fp;
1540 char *filename, *line;
1541
1542 filename = xasprintf("/var/lib/dpkg/info/%s.%s", package_name, control_name);
1543 fp = fopen_for_read(filename);
1544 free(filename);
1545 if (fp != NULL) {
1546 while ((line = xmalloc_fgetline(fp)) != NULL)
1547 llist_add_to(ll, line);
1548 fclose(fp);
1549 }
1550}
1551
1552static char FAST_FUNC filter_rename_config(archive_handle_t *archive_handle)
1553{
1554 int fd;
1555 char *name_ptr = archive_handle->file_header->name + 1;
1556
1557
1558 if (!find_list_entry(archive_handle->accept, name_ptr))
1559 return EXIT_SUCCESS;
1560
1561 fd = open(name_ptr, O_RDONLY);
1562 if (fd >= 0) {
1563 md5_ctx_t md5;
1564 char *md5line, *buf;
1565 int count;
1566
1567
1568 buf = xmalloc(4096);
1569 md5_begin(&md5);
1570 while ((count = safe_read(fd, buf, 4096)) > 0)
1571 md5_hash(&md5, buf, count);
1572 md5_end(&md5, buf);
1573 close(fd);
1574
1575 md5line = xmalloc(16 * 2 + 2 + strlen(name_ptr) + 1);
1576 sprintf(bin2hex(md5line, buf, 16), " %s", name_ptr);
1577 free(buf);
1578
1579
1580 if (find_list_entry(archive_handle->accept, md5line) == NULL) {
1581 printf("Warning: Creating %s as %s.dpkg-new\n", name_ptr, name_ptr);
1582 archive_handle->file_header->name = xasprintf("%s.dpkg-new", archive_handle->file_header->name);
1583 }
1584 free(md5line);
1585 }
1586 return EXIT_SUCCESS;
1587}
1588
1589static void FAST_FUNC data_extract_all_prefix(archive_handle_t *archive_handle)
1590{
1591 char *name_ptr = archive_handle->file_header->name;
1592
1593
1594 while (*name_ptr == '/')
1595 name_ptr++;
1596
1597 while (name_ptr[0] == '.') {
1598 if (name_ptr[1] == '.')
1599 name_ptr++;
1600 if (name_ptr[1] != '/')
1601 break;
1602 name_ptr += 2;
1603 }
1604
1605 if (name_ptr[0] != '\0') {
1606 archive_handle->file_header->name = xasprintf("%s%s", archive_handle->dpkg__buffer, name_ptr);
1607 data_extract_all(archive_handle);
1608 if (fnmatch("*.dpkg-new", archive_handle->file_header->name, 0) == 0) {
1609
1610 archive_handle->file_header->name[strlen(archive_handle->file_header->name) - 9] = '\0';
1611 }
1612 }
1613}
1614
1615enum {
1616
1617 OPT_configure = (1 << 0),
1618 OPT_install = (1 << 1),
1619 OPT_list_installed = (1 << 2),
1620 OPT_purge = (1 << 3),
1621 OPT_remove = (1 << 4),
1622 OPT_unpack = (1 << 5),
1623 OPTMASK_cmd = (1 << 6) - 1,
1624
1625 OPT_force = (1 << 6),
1626 OPT_force_ignore_depends = (1 << 7),
1627 OPT_force_confnew = (1 << 8),
1628 OPT_force_confold = (1 << 9),
1629};
1630
1631static void unpack_package(deb_file_t *deb_file)
1632{
1633 const char *package_name = name_hashtable[package_hashtable[deb_file->package]->name];
1634 const unsigned status_num = search_status_hashtable(package_name);
1635 const unsigned status_package_num = status_hashtable[status_num]->package;
1636 char *info_prefix;
1637 char *list_filename;
1638 archive_handle_t *archive_handle;
1639 FILE *out_stream;
1640 llist_t *accept_list;
1641 llist_t *conffile_list;
1642 int i;
1643
1644
1645 conffile_list = NULL;
1646 if (strcmp(name_hashtable[get_status(status_num, 3)], "installed") == 0) {
1647
1648 printf("Preparing to replace %s %s (using %s)...\n", package_name,
1649 name_hashtable[package_hashtable[status_package_num]->version],
1650 deb_file->filename);
1651
1652
1653 if (!(option_mask32 & OPT_force_confold))
1654 append_control_file_to_llist(package_name, "md5sums", &conffile_list);
1655
1656 remove_package(status_package_num, 0);
1657 } else {
1658 printf("Unpacking %s (from %s)...\n", package_name, deb_file->filename);
1659 }
1660
1661
1662 info_prefix = xasprintf("/var/lib/dpkg/info/%s.%s", package_name, "");
1663 archive_handle = init_archive_deb_ar(deb_file->filename);
1664 init_archive_deb_control(archive_handle);
1665
1666 accept_list = NULL;
1667 i = 0;
1668 while (i < ARRAY_SIZE(all_control_files)) {
1669 char *c = xasprintf("./%s", all_control_files[i]);
1670 llist_add_to(&accept_list, c);
1671 i++;
1672 }
1673 archive_handle->dpkg__sub_archive->accept = accept_list;
1674 archive_handle->dpkg__sub_archive->filter = filter_accept_list;
1675 archive_handle->dpkg__sub_archive->action_data = data_extract_all_prefix;
1676 archive_handle->dpkg__sub_archive->dpkg__buffer = info_prefix;
1677 archive_handle->dpkg__sub_archive->ah_flags |= ARCHIVE_UNLINK_OLD;
1678 unpack_ar_archive(archive_handle);
1679
1680
1681 run_package_script_or_die(package_name, "preinst");
1682
1683
1684 if (!(option_mask32 & OPT_force_confnew))
1685 append_control_file_to_llist(package_name, "conffiles", &conffile_list);
1686
1687
1688 archive_handle = init_archive_deb_ar(deb_file->filename);
1689 init_archive_deb_data(archive_handle);
1690 archive_handle->dpkg__sub_archive->accept = conffile_list;
1691
1692
1693
1694
1695 archive_handle->dpkg__sub_archive->ah_flags |= ARCHIVE_REMEMBER_NAMES | ARCHIVE_UNLINK_OLD;
1696 archive_handle->dpkg__sub_archive->filter = filter_rename_config;
1697 archive_handle->dpkg__sub_archive->action_data = data_extract_all_prefix;
1698 archive_handle->dpkg__sub_archive->dpkg__buffer = (char*)"/";
1699 unpack_ar_archive(archive_handle);
1700
1701
1702 list_filename = xasprintf("/var/lib/dpkg/info/%s.%s", package_name, "list");
1703 out_stream = xfopen_for_write(list_filename);
1704 archive_handle->dpkg__sub_archive->passed = llist_rev(archive_handle->dpkg__sub_archive->passed);
1705 while (archive_handle->dpkg__sub_archive->passed) {
1706 char *filename = llist_pop(&archive_handle->dpkg__sub_archive->passed);
1707
1708 fprintf(out_stream, "%s\n", filename);
1709 free(filename);
1710 }
1711 fclose(out_stream);
1712
1713
1714 set_status(status_num, "install", 1);
1715 set_status(status_num, "unpacked", 3);
1716
1717 free(info_prefix);
1718 free(list_filename);
1719}
1720
1721static void configure_package(deb_file_t *deb_file)
1722{
1723 const char *package_name = name_hashtable[package_hashtable[deb_file->package]->name];
1724 const char *package_version = name_hashtable[package_hashtable[deb_file->package]->version];
1725 const int status_num = search_status_hashtable(package_name);
1726
1727 printf("Setting up %s (%s)...\n", package_name, package_version);
1728
1729
1730
1731 run_package_script_or_die(package_name, "postinst");
1732
1733
1734 set_status(status_num, "install", 1);
1735 set_status(status_num, "installed", 3);
1736}
1737
1738int dpkg_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE;
1739int dpkg_main(int argc UNUSED_PARAM, char **argv)
1740{
1741 deb_file_t **deb_file = NULL;
1742 status_node_t *status_node;
1743 char *str_f;
1744 int opt;
1745 int package_num;
1746 int deb_count = 0;
1747 int state_status;
1748 int status_num;
1749 int i;
1750#if ENABLE_LONG_OPTS
1751 static const char dpkg_longopts[] ALIGN1 =
1752
1753
1754 "configure\0" No_argument "C"
1755 "force\0" Required_argument "F"
1756 "install\0" No_argument "i"
1757 "list\0" No_argument "l"
1758 "purge\0" No_argument "P"
1759 "remove\0" No_argument "r"
1760 "unpack\0" No_argument "u"
1761 "force-depends\0" No_argument "\xff"
1762 "force-confnew\0" No_argument "\xfe"
1763 "force-confold\0" No_argument "\xfd"
1764 ;
1765#endif
1766
1767 INIT_G();
1768
1769 IF_LONG_OPTS(applet_long_options = dpkg_longopts);
1770 opt = getopt32(argv, "CilPruF:", &str_f);
1771 argv += optind;
1772
1773 if (opt & OPT_force) {
1774 if (strcmp(str_f, "depends") == 0)
1775 opt |= OPT_force_ignore_depends;
1776 else if (strcmp(str_f, "confnew") == 0)
1777 opt |= OPT_force_confnew;
1778 else if (strcmp(str_f, "confold") == 0)
1779 opt |= OPT_force_confold;
1780 else
1781 bb_show_usage();
1782 option_mask32 = opt;
1783 }
1784
1785
1786
1787
1788
1789 if (!(opt & OPTMASK_cmd)
1790 || ((opt & OPTMASK_cmd) & ((opt & OPTMASK_cmd)-1))
1791 ) {
1792 bb_show_usage();
1793 }
1794
1795
1796 index_status_file("/var/lib/dpkg/status");
1797
1798
1799 if (opt & OPT_list_installed) {
1800 list_packages(argv[0]);
1801 return EXIT_SUCCESS;
1802 }
1803
1804
1805 while (*argv) {
1806
1807 deb_file = xrealloc_vector(deb_file, 2, deb_count);
1808 deb_file[deb_count] = xzalloc(sizeof(deb_file[0][0]));
1809 if (opt & (OPT_install | OPT_unpack)) {
1810
1811 archive_handle_t *archive_handle;
1812 llist_t *control_list = NULL;
1813
1814
1815 llist_add_to(&control_list, (char*)"./control");
1816 archive_handle = init_archive_deb_ar(argv[0]);
1817 init_archive_deb_control(archive_handle);
1818 deb_file[deb_count]->control_file = deb_extract_control_file_to_buffer(archive_handle, control_list);
1819 if (deb_file[deb_count]->control_file == NULL) {
1820 bb_error_msg_and_die("can't extract control file");
1821 }
1822 deb_file[deb_count]->filename = xstrdup(argv[0]);
1823 package_num = fill_package_struct(deb_file[deb_count]->control_file);
1824
1825 if (package_num == -1) {
1826 bb_error_msg("invalid control file in %s", argv[0]);
1827 argv++;
1828 continue;
1829 }
1830 deb_file[deb_count]->package = (unsigned) package_num;
1831
1832
1833 if (opt & (OPT_unpack | OPT_install)) {
1834
1835 status_num = search_status_hashtable(name_hashtable[package_hashtable[deb_file[deb_count]->package]->name]);
1836
1837 if (status_hashtable[status_num] == NULL
1838 || status_hashtable[status_num]->status == 0
1839 ) {
1840 status_node = xmalloc(sizeof(status_node_t));
1841 status_node->package = deb_file[deb_count]->package;
1842
1843
1844 status_node->status = search_name_hashtable("install reinstreq not-installed");
1845 status_hashtable[status_num] = status_node;
1846 } else {
1847 set_status(status_num, "install", 1);
1848 set_status(status_num, "reinstreq", 2);
1849 }
1850 }
1851 } else if (opt & (OPT_configure | OPT_purge | OPT_remove)) {
1852
1853 deb_file[deb_count]->package = search_package_hashtable(
1854 search_name_hashtable(argv[0]),
1855 search_name_hashtable("ANY"), VER_ANY);
1856 if (package_hashtable[deb_file[deb_count]->package] == NULL) {
1857 bb_error_msg_and_die("package %s is uninstalled or unknown", argv[0]);
1858 }
1859 package_num = deb_file[deb_count]->package;
1860 status_num = search_status_hashtable(name_hashtable[package_hashtable[package_num]->name]);
1861 state_status = get_status(status_num, 3);
1862
1863
1864 if (opt & OPT_remove) {
1865 if (strcmp(name_hashtable[state_status], "not-installed") == 0
1866 || strcmp(name_hashtable[state_status], "config-files") == 0
1867 ) {
1868 bb_error_msg_and_die("%s is already removed", name_hashtable[package_hashtable[package_num]->name]);
1869 }
1870 set_status(status_num, "deinstall", 1);
1871 } else if (opt & OPT_purge) {
1872
1873 if (strcmp(name_hashtable[state_status], "not-installed") == 0) {
1874 bb_error_msg_and_die("%s is already purged", name_hashtable[package_hashtable[package_num]->name]);
1875 }
1876 set_status(status_num, "purge", 1);
1877 }
1878 }
1879 deb_count++;
1880 argv++;
1881 }
1882 if (!deb_count)
1883 bb_error_msg_and_die("no package files specified");
1884 deb_file[deb_count] = NULL;
1885
1886
1887 if (!(opt & OPT_force_ignore_depends)) {
1888 if (!check_deps(deb_file, 0 )) {
1889 bb_error_msg_and_die("dependency check failed");
1890 }
1891 }
1892
1893
1894 for (i = 0; i < deb_count; i++) {
1895
1896 if (opt & OPT_remove) {
1897 remove_package(deb_file[i]->package, 1);
1898 }
1899 else if (opt & OPT_purge) {
1900 purge_package(deb_file[i]->package);
1901 }
1902 else if (opt & OPT_unpack) {
1903 unpack_package(deb_file[i]);
1904 }
1905 else if (opt & OPT_install) {
1906 unpack_package(deb_file[i]);
1907
1908 }
1909 else if (opt & OPT_configure) {
1910 configure_package(deb_file[i]);
1911 }
1912 }
1913
1914 if (opt & OPT_install) {
1915 for (i = 0; i < deb_count; i++)
1916 configure_package(deb_file[i]);
1917 }
1918
1919 write_status_file(deb_file);
1920
1921 if (ENABLE_FEATURE_CLEAN_UP) {
1922 for (i = 0; i < deb_count; i++) {
1923 free(deb_file[i]->control_file);
1924 free(deb_file[i]->filename);
1925 free(deb_file[i]);
1926 }
1927
1928 free(deb_file);
1929
1930 for (i = 0; i < NAME_HASH_PRIME; i++) {
1931 free(name_hashtable[i]);
1932 }
1933
1934 for (i = 0; i < PACKAGE_HASH_PRIME; i++) {
1935 free_package(package_hashtable[i]);
1936 }
1937
1938 for (i = 0; i < STATUS_HASH_PRIME; i++) {
1939 free(status_hashtable[i]);
1940 }
1941
1942 free(status_hashtable);
1943 free(package_hashtable);
1944 free(name_hashtable);
1945 }
1946
1947 return EXIT_SUCCESS;
1948}
1949