diff options
author | Glenn L McGrath <bug1@ihug.co.nz> | 2003-11-28 22:38:14 +0000 |
---|---|---|
committer | Glenn L McGrath <bug1@ihug.co.nz> | 2003-11-28 22:38:14 +0000 |
commit | b8c3a5453120af6509ddd7d66dffc0b8ef417629 (patch) | |
tree | 891d2927d79940e4f1351525484b42ea6c379b52 | |
parent | 11e69471be27de28aefef931ec26912a6da7bed7 (diff) | |
download | busybox-w32-b8c3a5453120af6509ddd7d66dffc0b8ef417629.tar.gz busybox-w32-b8c3a5453120af6509ddd7d66dffc0b8ef417629.tar.bz2 busybox-w32-b8c3a5453120af6509ddd7d66dffc0b8ef417629.zip |
Patch from Ian Campbell, fix or'ed dependencies and handle virtual
dependencies.
-rw-r--r-- | archival/dpkg.c | 316 |
1 files changed, 237 insertions, 79 deletions
diff --git a/archival/dpkg.c b/archival/dpkg.c index 93f9f0673..2ebbbdf4e 100644 --- a/archival/dpkg.c +++ b/archival/dpkg.c | |||
@@ -390,7 +390,53 @@ int search_package_hashtable(const unsigned int name, const unsigned int version | |||
390 | } | 390 | } |
391 | 391 | ||
392 | /* | 392 | /* |
393 | * This function searches through the entire package_hashtable looking | ||
394 | * for a package which provides "needle". It returns the index into | ||
395 | * the package_hashtable for the provining package. | ||
396 | * | ||
397 | * needle is the index into name_hashtable of the package we are | ||
398 | * looking for. | ||
399 | * | ||
400 | * start_at is the index in the package_hashtable to start looking | ||
401 | * at. If start_at is -1 then start at the beginning. This is to allow | ||
402 | * for repeated searches since more than one package might provide | ||
403 | * needle. | ||
404 | * | ||
405 | * FIXME: I don't think this is very efficient, but I thought I'd keep | ||
406 | * it simple for now until it proves to be a problem. | ||
407 | */ | ||
408 | int search_for_provides(int needle, int start_at) { | ||
409 | int i, j; | ||
410 | common_node_t *p; | ||
411 | for (i = start_at + 1; i < PACKAGE_HASH_PRIME; i++) { | ||
412 | p = package_hashtable[i]; | ||
413 | if ( p == NULL ) continue; | ||
414 | for(j = 0; j < p->num_of_edges; j++) | ||
415 | if ( p->edge[j]->type == EDGE_PROVIDES && p->edge[j]->name == needle ) | ||
416 | return i; | ||
417 | } | ||
418 | return -1; | ||
419 | } | ||
420 | |||
421 | /* | ||
422 | * Add an edge to a node | ||
423 | */ | ||
424 | void add_edge_to_node(common_node_t *node, edge_t *edge) | ||
425 | { | ||
426 | node->num_of_edges++; | ||
427 | node->edge = xrealloc(node->edge, sizeof(edge_t) * (node->num_of_edges + 1)); | ||
428 | node->edge[node->num_of_edges - 1] = edge; | ||
429 | } | ||
430 | |||
431 | /* | ||
393 | * Create one new node and one new edge for every dependency. | 432 | * Create one new node and one new edge for every dependency. |
433 | * | ||
434 | * Dependencies which contain multiple alternatives are represented as | ||
435 | * an EDGE_OR_PRE_DEPENDS or EDGE_OR_DEPENDS node, followed by a | ||
436 | * number of EDGE_PRE_DEPENDS or EDGE_DEPENDS nodes. The name field of | ||
437 | * the OR edge contains the full dependency string while the version | ||
438 | * field contains the number of EDGE nodes which follow as part of | ||
439 | * this alternative. | ||
394 | */ | 440 | */ |
395 | void add_split_dependencies(common_node_t *parent_node, const char *whole_line, unsigned int edge_type) | 441 | void add_split_dependencies(common_node_t *parent_node, const char *whole_line, unsigned int edge_type) |
396 | { | 442 | { |
@@ -402,25 +448,33 @@ void add_split_dependencies(common_node_t *parent_node, const char *whole_line, | |||
402 | char *field2; | 448 | char *field2; |
403 | char *version; | 449 | char *version; |
404 | edge_t *edge; | 450 | edge_t *edge; |
451 | edge_t *or_edge; | ||
405 | int offset_ch; | 452 | int offset_ch; |
406 | int type; | ||
407 | 453 | ||
408 | field = strtok_r(line, ",", &line_ptr1); | 454 | field = strtok_r(line, ",", &line_ptr1); |
409 | do { | 455 | do { |
456 | /* skip leading spaces */ | ||
457 | field += strspn(field, " "); | ||
410 | line2 = bb_xstrdup(field); | 458 | line2 = bb_xstrdup(field); |
411 | field2 = strtok_r(line2, "|", &line_ptr2); | 459 | field2 = strtok_r(line2, "|", &line_ptr2); |
412 | if ((edge_type == EDGE_DEPENDS) && (strcmp(field, field2) != 0)) { | 460 | if ( (edge_type == EDGE_DEPENDS || edge_type == EDGE_PRE_DEPENDS) && |
413 | type = EDGE_OR_DEPENDS; | 461 | (strcmp(field, field2) != 0)) { |
414 | } | 462 | or_edge = (edge_t *)xmalloc(sizeof(edge_t)); |
415 | else if ((edge_type == EDGE_PRE_DEPENDS) && (strcmp(field, field2) != 0)) { | 463 | or_edge->type = edge_type + 1; |
416 | type = EDGE_OR_PRE_DEPENDS; | ||
417 | } else { | 464 | } else { |
418 | type = edge_type; | 465 | or_edge = NULL; |
466 | } | ||
467 | |||
468 | if ( or_edge ) { | ||
469 | or_edge->name = search_name_hashtable(field); | ||
470 | or_edge->version = 0; // tracks the number of altenatives | ||
471 | |||
472 | add_edge_to_node(parent_node, or_edge); | ||
419 | } | 473 | } |
420 | 474 | ||
421 | do { | 475 | do { |
422 | edge = (edge_t *) xmalloc(sizeof(edge_t)); | 476 | edge = (edge_t *) xmalloc(sizeof(edge_t)); |
423 | edge->type = type; | 477 | edge->type = edge_type; |
424 | 478 | ||
425 | /* Skip any extra leading spaces */ | 479 | /* Skip any extra leading spaces */ |
426 | field2 += strspn(field2, " "); | 480 | field2 += strspn(field2, " "); |
@@ -470,11 +524,11 @@ void add_split_dependencies(common_node_t *parent_node, const char *whole_line, | |||
470 | /* Get the dependency name */ | 524 | /* Get the dependency name */ |
471 | field2[strcspn(field2, " (")] = '\0'; | 525 | field2[strcspn(field2, " (")] = '\0'; |
472 | edge->name = search_name_hashtable(field2); | 526 | edge->name = search_name_hashtable(field2); |
473 | 527 | ||
474 | /* link the new edge to the current node */ | 528 | if ( or_edge ) |
475 | parent_node->num_of_edges++; | 529 | or_edge->version++; |
476 | parent_node->edge = xrealloc(parent_node->edge, sizeof(edge_t) * (parent_node->num_of_edges + 1)); | 530 | |
477 | parent_node->edge[parent_node->num_of_edges - 1] = edge; | 531 | add_edge_to_node(parent_node, edge); |
478 | } while ((field2 = strtok_r(NULL, "|", &line_ptr2)) != NULL); | 532 | } while ((field2 = strtok_r(NULL, "|", &line_ptr2)) != NULL); |
479 | free(line2); | 533 | free(line2); |
480 | } while ((field = strtok_r(NULL, ",", &line_ptr1)) != NULL); | 534 | } while ((field = strtok_r(NULL, ",", &line_ptr1)) != NULL); |
@@ -490,7 +544,8 @@ void free_package(common_node_t *node) | |||
490 | for (i = 0; i < node->num_of_edges; i++) { | 544 | for (i = 0; i < node->num_of_edges; i++) { |
491 | free(node->edge[i]); | 545 | free(node->edge[i]); |
492 | } | 546 | } |
493 | free(node->edge); | 547 | if ( node->edge ) |
548 | free(node->edge); | ||
494 | free(node); | 549 | free(node); |
495 | } | 550 | } |
496 | } | 551 | } |
@@ -627,6 +682,31 @@ void set_status(const unsigned int status_node_num, const char *new_value, const | |||
627 | return; | 682 | return; |
628 | } | 683 | } |
629 | 684 | ||
685 | const char *describe_status(int status_num) { | ||
686 | int status_want, status_state ; | ||
687 | if ( status_hashtable[status_num] == NULL || status_hashtable[status_num]->status == 0 ) | ||
688 | return "is not installed or flagged to be installed\n"; | ||
689 | |||
690 | status_want = get_status(status_num, 1); | ||
691 | status_state = get_status(status_num, 3); | ||
692 | |||
693 | if ( status_state == search_name_hashtable("installed") ) { | ||
694 | if ( status_want == search_name_hashtable("install") ) | ||
695 | return "is installed"; | ||
696 | if ( status_want == search_name_hashtable("deinstall") ) | ||
697 | return "is marked to be removed"; | ||
698 | if ( status_want == search_name_hashtable("purge") ) | ||
699 | return "is marked to be purged"; | ||
700 | } | ||
701 | if ( status_want == search_name_hashtable("unknown") ) | ||
702 | return "is in an indeterminate state"; | ||
703 | if ( status_want == search_name_hashtable("install") ) | ||
704 | return "is marked to be installed"; | ||
705 | |||
706 | return "is not installed or flagged to be installed"; | ||
707 | } | ||
708 | |||
709 | |||
630 | void index_status_file(const char *filename) | 710 | void index_status_file(const char *filename) |
631 | { | 711 | { |
632 | FILE *status_file; | 712 | FILE *status_file; |
@@ -659,7 +739,7 @@ void index_status_file(const char *filename) | |||
659 | return; | 739 | return; |
660 | } | 740 | } |
661 | 741 | ||
662 | 742 | #if 0 /* this code is no longer used */ | |
663 | char *get_depends_field(common_node_t *package, const int depends_type) | 743 | char *get_depends_field(common_node_t *package, const int depends_type) |
664 | { | 744 | { |
665 | char *depends = NULL; | 745 | char *depends = NULL; |
@@ -730,6 +810,7 @@ char *get_depends_field(common_node_t *package, const int depends_type) | |||
730 | } | 810 | } |
731 | return(depends); | 811 | return(depends); |
732 | } | 812 | } |
813 | #endif | ||
733 | 814 | ||
734 | void write_buffer_no_status(FILE *new_status_file, const char *control_buffer) | 815 | void write_buffer_no_status(FILE *new_status_file, const char *control_buffer) |
735 | { | 816 | { |
@@ -890,13 +971,34 @@ void write_status_file(deb_file_t **deb_file) | |||
890 | } | 971 | } |
891 | } | 972 | } |
892 | 973 | ||
974 | /* This function returns TRUE if the given package can statisfy a | ||
975 | * dependency of type depend_type. | ||
976 | * | ||
977 | * A pre-depends is statisfied only if a package is already installed, | ||
978 | * which a regular depends can be satisfied by a package which we want | ||
979 | * to install. | ||
980 | */ | ||
981 | int package_satisfies_dependency(int package, int depend_type) | ||
982 | { | ||
983 | int status_num = search_status_hashtable(name_hashtable[package_hashtable[package]->name]); | ||
984 | |||
985 | /* status could be unknown if package is a pure virtual | ||
986 | * provides which cannot satisfy any dependency by itself. | ||
987 | */ | ||
988 | if ( status_hashtable[status_num] == NULL ) | ||
989 | return 0; | ||
990 | |||
991 | switch (depend_type) { | ||
992 | case EDGE_PRE_DEPENDS: return get_status(status_num, 3) == search_name_hashtable("installed"); | ||
993 | case EDGE_DEPENDS: return get_status(status_num, 1) == search_name_hashtable("install"); | ||
994 | } | ||
995 | return 0; | ||
996 | } | ||
997 | |||
893 | int check_deps(deb_file_t **deb_file, int deb_start, int dep_max_count) | 998 | int check_deps(deb_file_t **deb_file, int deb_start, int dep_max_count) |
894 | { | 999 | { |
895 | int *conflicts = NULL; | 1000 | int *conflicts = NULL; |
896 | int conflicts_num = 0; | 1001 | int conflicts_num = 0; |
897 | int state_status; | ||
898 | int state_flag; | ||
899 | int state_want; | ||
900 | int i = deb_start; | 1002 | int i = deb_start; |
901 | int j; | 1003 | int j; |
902 | 1004 | ||
@@ -952,21 +1054,17 @@ int check_deps(deb_file_t **deb_file, int deb_start, int dep_max_count) | |||
952 | 1054 | ||
953 | for (j = 0; j < package_node->num_of_edges; j++) { | 1055 | for (j = 0; j < package_node->num_of_edges; j++) { |
954 | const edge_t *package_edge = package_node->edge[j]; | 1056 | const edge_t *package_edge = package_node->edge[j]; |
955 | const unsigned int package_num = | ||
956 | search_package_hashtable(package_edge->name, | ||
957 | package_edge->version, package_edge->operator); | ||
958 | 1057 | ||
959 | if (package_edge->type == EDGE_CONFLICTS) { | 1058 | if (package_edge->type == EDGE_CONFLICTS) { |
1059 | const unsigned int package_num = | ||
1060 | search_package_hashtable(package_edge->name, | ||
1061 | package_edge->version, | ||
1062 | package_edge->operator); | ||
960 | int result = 0; | 1063 | int result = 0; |
961 | if (package_hashtable[package_num] != NULL) { | 1064 | if (package_hashtable[package_num] != NULL) { |
962 | status_num = search_status_hashtable(name_hashtable[package_hashtable[package_num]->name]); | 1065 | status_num = search_status_hashtable(name_hashtable[package_hashtable[package_num]->name]); |
963 | state_status = get_status(status_num, 3); | ||
964 | state_flag = get_status(status_num, 1); | ||
965 | |||
966 | result = (state_status == search_name_hashtable("installed")) || | ||
967 | (state_flag == search_name_hashtable("want-install")); | ||
968 | 1066 | ||
969 | if (result) { | 1067 | if (get_status(status_num, 1) == search_name_hashtable("install")) { |
970 | result = test_version(package_hashtable[deb_file[i]->package]->version, | 1068 | result = test_version(package_hashtable[deb_file[i]->package]->version, |
971 | package_edge->version, package_edge->operator); | 1069 | package_edge->version, package_edge->operator); |
972 | } | 1070 | } |
@@ -984,66 +1082,123 @@ int check_deps(deb_file_t **deb_file, int deb_start, int dep_max_count) | |||
984 | 1082 | ||
985 | 1083 | ||
986 | /* Check dependendcies */ | 1084 | /* Check dependendcies */ |
987 | i = 0; | 1085 | for (i = 0; i < PACKAGE_HASH_PRIME; i++) { |
988 | while (deb_file[i] != NULL) { | ||
989 | const common_node_t *package_node = package_hashtable[deb_file[i]->package]; | ||
990 | int status_num = 0; | 1086 | int status_num = 0; |
1087 | int number_of_alternatives = 0; | ||
1088 | const edge_t * root_of_alternatives; | ||
1089 | const common_node_t *package_node = package_hashtable[i]; | ||
991 | 1090 | ||
992 | status_num = search_status_hashtable(name_hashtable[package_node->name]); | 1091 | /* If the package node does not exist then this |
993 | state_status = get_status(status_num, 3); | 1092 | * package is a virtual one. In which case there are |
994 | state_want = get_status(status_num, 1); | 1093 | * no dependencies to check. |
1094 | */ | ||
1095 | if ( package_node == NULL ) continue; | ||
995 | 1096 | ||
996 | if (state_status == search_name_hashtable("installed")) { | 1097 | status_num = search_status_hashtable(name_hashtable[package_node->name]); |
997 | i++; | 1098 | |
1099 | /* If there is no status then this package is a | ||
1100 | * virtual one provided by something else. In which | ||
1101 | * case there are no dependencies to check. | ||
1102 | */ | ||
1103 | if ( status_hashtable[status_num] == NULL ) continue; | ||
1104 | |||
1105 | /* If we don't want this package installed then we may | ||
1106 | * as well ignore it's dependencies. | ||
1107 | */ | ||
1108 | if (get_status(status_num, 1) != search_name_hashtable("install")) { | ||
998 | continue; | 1109 | continue; |
999 | } | 1110 | } |
1000 | 1111 | ||
1001 | for (j = 0; j < package_hashtable[deb_file[i]->package]->num_of_edges; j++) { | 1112 | #if 0 |
1113 | /* This might be needed so we don't complain about | ||
1114 | * things which are broken but unrelated to the | ||
1115 | * packages that are currently being installed | ||
1116 | */ | ||
1117 | if (state_status == search_name_hashtable("installed")) | ||
1118 | continue; | ||
1119 | #endif | ||
1120 | |||
1121 | /* This code is tested only for EDGE_DEPENDS, sine I | ||
1122 | * have no suitable pre-depends available. There is no | ||
1123 | * reason that it shouldn't work though :-) | ||
1124 | */ | ||
1125 | for (j = 0; j < package_node->num_of_edges; j++) { | ||
1002 | const edge_t *package_edge = package_node->edge[j]; | 1126 | const edge_t *package_edge = package_node->edge[j]; |
1003 | unsigned int package_num; | 1127 | unsigned int package_num; |
1128 | |||
1129 | if ( package_edge->type == EDGE_OR_PRE_DEPENDS || | ||
1130 | package_edge->type == EDGE_OR_DEPENDS ) { /* start an EDGE_OR_ list */ | ||
1131 | number_of_alternatives = package_edge->version; | ||
1132 | root_of_alternatives = package_edge; | ||
1133 | continue; | ||
1134 | } else if ( number_of_alternatives == 0 ) { /* not in the middle of an EDGE_OR_ list */ | ||
1135 | number_of_alternatives = 1; | ||
1136 | root_of_alternatives = NULL; | ||
1137 | } | ||
1004 | 1138 | ||
1005 | package_num = search_package_hashtable(package_edge->name, package_edge->version, package_edge->operator); | 1139 | package_num = search_package_hashtable(package_edge->name, package_edge->version, package_edge->operator); |
1006 | 1140 | ||
1007 | switch (package_edge->type) { | 1141 | if (package_edge->type == EDGE_PRE_DEPENDS || |
1008 | case(EDGE_PRE_DEPENDS): | 1142 | package_edge->type == EDGE_DEPENDS ) { |
1009 | case(EDGE_OR_PRE_DEPENDS): { | 1143 | int result=1; |
1010 | int result=1; | 1144 | status_num = 0; |
1011 | /* It must be already installed */ | 1145 | |
1012 | /* NOTE: This is untested, nothing apropriate in my status file */ | 1146 | /* If we are inside an alternative then check |
1013 | if (package_hashtable[package_num] != NULL) { | 1147 | * this edge is the right type. |
1014 | status_num = search_status_hashtable(name_hashtable[package_hashtable[package_num]->name]); | 1148 | * |
1015 | state_status = get_status(status_num, 3); | 1149 | * EDGE_DEPENDS == OR_DEPENDS -1 |
1016 | state_want = get_status(status_num, 1); | 1150 | * EDGE_PRE_DEPENDS == OR_PRE_DEPENDS -1 |
1017 | result = (state_status != search_name_hashtable("installed")); | 1151 | */ |
1152 | if ( root_of_alternatives && package_edge->type != root_of_alternatives->type - 1) | ||
1153 | bb_error_msg_and_die("Fatal error. Package dependencies corrupt: %d != %d - 1 \n", | ||
1154 | package_edge->type, root_of_alternatives->type); | ||
1155 | |||
1156 | if (package_hashtable[package_num] != NULL) | ||
1157 | result = !package_satisfies_dependency(package_num, package_edge->type); | ||
1158 | |||
1159 | if (result) { /* check for other package which provide what we are looking for */ | ||
1160 | int provider = -1; | ||
1161 | |||
1162 | while ( (provider = search_for_provides(package_edge->name, provider) ) > -1 ) { | ||
1163 | if ( package_hashtable[provider] == NULL ) { | ||
1164 | printf("Have a provider but no package information for it\n"); | ||
1165 | continue; | ||
1166 | } | ||
1167 | result = !package_satisfies_dependency(provider, package_edge->type); | ||
1168 | |||
1169 | if ( result == 0 ) | ||
1170 | break; | ||
1018 | } | 1171 | } |
1172 | } | ||
1019 | 1173 | ||
1020 | if (result) { | 1174 | /* It must be already installed, or to be installed */ |
1021 | bb_error_msg_and_die("Package %s pre-depends on %s, but it is not installed", | 1175 | number_of_alternatives--; |
1176 | if (result && number_of_alternatives == 0) { | ||
1177 | if ( root_of_alternatives ) | ||
1178 | bb_error_msg_and_die( | ||
1179 | "Package %s %sdepends on %s, " | ||
1180 | "which cannot be satisfied", | ||
1022 | name_hashtable[package_node->name], | 1181 | name_hashtable[package_node->name], |
1023 | name_hashtable[package_edge->name]); | 1182 | package_edge->type == EDGE_PRE_DEPENDS ? "pre-" : "", |
1024 | } | 1183 | name_hashtable[root_of_alternatives->name]); |
1025 | break; | 1184 | else |
1026 | } | 1185 | bb_error_msg_and_die( |
1027 | case(EDGE_DEPENDS): | 1186 | "Package %s %sdepends on %s, which %s\n", |
1028 | case(EDGE_OR_DEPENDS): { | ||
1029 | int result=1; | ||
1030 | if (package_hashtable[package_num] != NULL) { | ||
1031 | status_num = search_status_hashtable(name_hashtable[package_hashtable[package_num]->name]); | ||
1032 | state_status = get_status(status_num, 3); | ||
1033 | state_want = get_status(status_num, 1); | ||
1034 | result=(state_status != search_name_hashtable("installed")) && (state_want != search_name_hashtable("want-install")); | ||
1035 | } | ||
1036 | /* It must be already installed, or to be installed */ | ||
1037 | if (result) { | ||
1038 | bb_error_msg_and_die("Package %s depends on %s, but it is not installed, or flaged to be installed", | ||
1039 | name_hashtable[package_node->name], | 1187 | name_hashtable[package_node->name], |
1040 | name_hashtable[package_edge->name]); | 1188 | package_edge->type == EDGE_PRE_DEPENDS ? "pre-" : "", |
1041 | } | 1189 | name_hashtable[package_edge->name], |
1042 | break; | 1190 | describe_status(status_num)); |
1191 | } else if ( result == 0 && number_of_alternatives ) { | ||
1192 | /* we've found a package which | ||
1193 | * satisfies the dependency, | ||
1194 | * so skip over the rest of | ||
1195 | * the alternatives. | ||
1196 | */ | ||
1197 | j += number_of_alternatives; | ||
1198 | number_of_alternatives = 0; | ||
1043 | } | 1199 | } |
1044 | } | 1200 | } |
1045 | } | 1201 | } |
1046 | i++; | ||
1047 | } | 1202 | } |
1048 | free(conflicts); | 1203 | free(conflicts); |
1049 | return(TRUE); | 1204 | return(TRUE); |
@@ -1260,7 +1415,6 @@ void remove_package(const unsigned int package_num, int noisy) | |||
1260 | rename(conffile_name, list_name); | 1415 | rename(conffile_name, list_name); |
1261 | 1416 | ||
1262 | /* Change package status */ | 1417 | /* Change package status */ |
1263 | set_status(status_num, "deinstall", 1); | ||
1264 | set_status(status_num, "config-files", 3); | 1418 | set_status(status_num, "config-files", 3); |
1265 | } | 1419 | } |
1266 | 1420 | ||
@@ -1303,7 +1457,6 @@ void purge_package(const unsigned int package_num) | |||
1303 | } | 1457 | } |
1304 | 1458 | ||
1305 | /* Change package status */ | 1459 | /* Change package status */ |
1306 | set_status(status_num, "purge", 1); | ||
1307 | set_status(status_num, "not-installed", 3); | 1460 | set_status(status_num, "not-installed", 3); |
1308 | } | 1461 | } |
1309 | 1462 | ||
@@ -1501,6 +1654,7 @@ int dpkg_main(int argc, char **argv) | |||
1501 | if (strcmp(optarg, "depends") == 0) { | 1654 | if (strcmp(optarg, "depends") == 0) { |
1502 | dpkg_opt |= dpkg_opt_force_ignore_depends; | 1655 | dpkg_opt |= dpkg_opt_force_ignore_depends; |
1503 | } | 1656 | } |
1657 | break; | ||
1504 | case 'i': | 1658 | case 'i': |
1505 | dpkg_opt |= dpkg_opt_install; | 1659 | dpkg_opt |= dpkg_opt_install; |
1506 | dpkg_opt |= dpkg_opt_filename; | 1660 | dpkg_opt |= dpkg_opt_filename; |
@@ -1566,19 +1720,20 @@ int dpkg_main(int argc, char **argv) | |||
1566 | 1720 | ||
1567 | /* Add the package to the status hashtable */ | 1721 | /* Add the package to the status hashtable */ |
1568 | if ((dpkg_opt & dpkg_opt_unpack) || (dpkg_opt & dpkg_opt_install)) { | 1722 | if ((dpkg_opt & dpkg_opt_unpack) || (dpkg_opt & dpkg_opt_install)) { |
1569 | status_node = (status_node_t *) xmalloc(sizeof(status_node_t)); | ||
1570 | status_node->package = deb_file[deb_count]->package; | ||
1571 | /* Try and find a currently installed version of this package */ | 1723 | /* Try and find a currently installed version of this package */ |
1572 | status_num = search_status_hashtable(name_hashtable[package_hashtable[deb_file[deb_count]->package]->name]); | 1724 | status_num = search_status_hashtable(name_hashtable[package_hashtable[deb_file[deb_count]->package]->name]); |
1573 | /* If no previous entry was found initialise a new entry */ | 1725 | /* If no previous entry was found initialise a new entry */ |
1574 | if ((status_hashtable[status_num] == NULL) || | 1726 | if ((status_hashtable[status_num] == NULL) || |
1575 | (status_hashtable[status_num]->status == 0)) { | 1727 | (status_hashtable[status_num]->status == 0)) { |
1728 | status_node = (status_node_t *) xmalloc(sizeof(status_node_t)); | ||
1729 | status_node->package = deb_file[deb_count]->package; | ||
1576 | /* reinstreq isnt changed to "ok" until the package control info | 1730 | /* reinstreq isnt changed to "ok" until the package control info |
1577 | * is written to the status file*/ | 1731 | * is written to the status file*/ |
1578 | status_node->status = search_name_hashtable("want-install reinstreq not-installed"); | 1732 | status_node->status = search_name_hashtable("install reinstreq not-installed"); |
1579 | status_hashtable[status_num] = status_node; | 1733 | status_hashtable[status_num] = status_node; |
1580 | } else { | 1734 | } else { |
1581 | status_hashtable[status_num]->status = search_name_hashtable("want-install reinstreq installed"); | 1735 | set_status(status_num, "install", 1); |
1736 | set_status(status_num, "reinstreq", 2); | ||
1582 | } | 1737 | } |
1583 | } | 1738 | } |
1584 | } | 1739 | } |
@@ -1591,20 +1746,24 @@ int dpkg_main(int argc, char **argv) | |||
1591 | if (package_hashtable[deb_file[deb_count]->package] == NULL) { | 1746 | if (package_hashtable[deb_file[deb_count]->package] == NULL) { |
1592 | bb_error_msg_and_die("Package %s is uninstalled or unknown\n", argv[optind]); | 1747 | bb_error_msg_and_die("Package %s is uninstalled or unknown\n", argv[optind]); |
1593 | } | 1748 | } |
1594 | state_status = get_status(search_status_hashtable(name_hashtable[package_hashtable[deb_file[deb_count]->package]->name]), 3); | 1749 | package_num = deb_file[deb_count]->package; |
1750 | status_num = search_status_hashtable(name_hashtable[package_hashtable[package_num]->name]); | ||
1751 | state_status = get_status(status_num, 3); | ||
1595 | 1752 | ||
1596 | /* check package status is "installed" */ | 1753 | /* check package status is "installed" */ |
1597 | if (dpkg_opt & dpkg_opt_remove) { | 1754 | if (dpkg_opt & dpkg_opt_remove) { |
1598 | if ((strcmp(name_hashtable[state_status], "not-installed") == 0) || | 1755 | if ((strcmp(name_hashtable[state_status], "not-installed") == 0) || |
1599 | (strcmp(name_hashtable[state_status], "config-files") == 0)) { | 1756 | (strcmp(name_hashtable[state_status], "config-files") == 0)) { |
1600 | bb_error_msg_and_die("%s is already removed.", name_hashtable[package_hashtable[deb_file[deb_count]->package]->name]); | 1757 | bb_error_msg_and_die("%s is already removed.", name_hashtable[package_hashtable[package_num]->name]); |
1601 | } | 1758 | } |
1759 | set_status(status_num, "deinstall", 1); | ||
1602 | } | 1760 | } |
1603 | else if (dpkg_opt & dpkg_opt_purge) { | 1761 | else if (dpkg_opt & dpkg_opt_purge) { |
1604 | /* if package status is "conf-files" then its ok */ | 1762 | /* if package status is "conf-files" then its ok */ |
1605 | if (strcmp(name_hashtable[state_status], "not-installed") == 0) { | 1763 | if (strcmp(name_hashtable[state_status], "not-installed") == 0) { |
1606 | bb_error_msg_and_die("%s is already purged.", name_hashtable[package_hashtable[deb_file[deb_count]->package]->name]); | 1764 | bb_error_msg_and_die("%s is already purged.", name_hashtable[package_hashtable[package_num]->name]); |
1607 | } | 1765 | } |
1766 | set_status(status_num, "purge", 1); | ||
1608 | } | 1767 | } |
1609 | } | 1768 | } |
1610 | deb_count++; | 1769 | deb_count++; |
@@ -1613,7 +1772,6 @@ int dpkg_main(int argc, char **argv) | |||
1613 | deb_file[deb_count] = NULL; | 1772 | deb_file[deb_count] = NULL; |
1614 | 1773 | ||
1615 | /* Check that the deb file arguments are installable */ | 1774 | /* Check that the deb file arguments are installable */ |
1616 | /* TODO: check dependencies before removing */ | ||
1617 | if ((dpkg_opt & dpkg_opt_force_ignore_depends) != dpkg_opt_force_ignore_depends) { | 1775 | if ((dpkg_opt & dpkg_opt_force_ignore_depends) != dpkg_opt_force_ignore_depends) { |
1618 | if (!check_deps(deb_file, 0, deb_count)) { | 1776 | if (!check_deps(deb_file, 0, deb_count)) { |
1619 | bb_error_msg_and_die("Dependency check failed"); | 1777 | bb_error_msg_and_die("Dependency check failed"); |