Changeset 1770 in MondoRescue for branches/stable/mindi-busybox/archival/dpkg.c
- Timestamp:
- Nov 6, 2007, 11:01:53 AM (16 years ago)
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
branches/stable/mindi-busybox/archival/dpkg.c
r821 r1770 1 /* vi: set sw=4 ts=4: */ 1 2 /* 2 * Mini dpkg implementation for busybox.3 * This is not meant as a replacement for dpkg3 * mini dpkg implementation for busybox. 4 * this is not meant as a replacement for dpkg 4 5 * 5 * Written By Glenn McGrath with the help of others6 * Copyright (C) 2001 by Glenn McGrath6 * written by glenn mcgrath with the help of others 7 * copyright (c) 2001 by glenn mcgrath 7 8 * 8 * Started life as a busybox implementation of udpkg9 * started life as a busybox implementation of udpkg 9 10 * 10 * Licensed under GPLv2 or later, see file LICENSEin this tarball for details.11 * licensed under gplv2 or later, see file license in this tarball for details. 11 12 */ 12 13 13 14 /* 14 * Known difference between busybox dpkg and the official dpkg that i don't15 * known difference between busybox dpkg and the official dpkg that i don't 15 16 * consider important, its worth keeping a note of differences anyway, just to 16 17 * make it easier to maintain. 17 * - The first value for the Confflile: field isnt placed on a new line.18 * - When installing a package the Status: field is placed at the end of the19 * section, rather than just after the Package: field.18 * - the first value for the confflile: field isnt placed on a new line. 19 * - when installing a package the status: field is placed at the end of the 20 * section, rather than just after the package: field. 20 21 * 21 * Bugs that need to be fixed22 * bugs that need to be fixed 22 23 * - (unknown, please let me know when you find any) 23 24 * 24 25 */ 25 26 26 #include <fcntl.h> 27 #include <getopt.h> 28 #include <stdlib.h> 29 #include <string.h> 30 #include <unistd.h> 27 #include "libbb.h" 31 28 #include "unarchive.h" 32 #include "busybox.h" 33 34 /* NOTE: If you vary HASH_PRIME sizes be aware, 35 * 1) Tweaking these will have a big effect on how much memory this program uses. 36 * 2) For computational efficiency these hash tables should be at least 20% 29 30 /* note: if you vary hash_prime sizes be aware, 31 * 1) tweaking these will have a big effect on how much memory this program uses. 32 * 2) for computational efficiency these hash tables should be at least 20% 37 33 * larger than the maximum number of elements stored in it. 38 * 3) All _HASH_PRIME's must be a prime number or chaos is assured, if your looking34 * 3) all _hash_prime's must be a prime number or chaos is assured, if your looking 39 35 * for a prime, try http://www.utm.edu/research/primes/lists/small/10000.txt 40 * 4) If you go bigger than 15 bits you may get into trouble (untested) as its41 * sometimes cast to an unsigned int, if you go to 16 bit you will overlap36 * 4) if you go bigger than 15 bits you may get into trouble (untested) as its 37 * sometimes cast to an unsigned, if you go to 16 bit you will overlap 42 38 * int's and chaos is assured, 16381 is the max prime for 14 bit field 43 39 */ … … 47 43 * as there a lot of duplicate version numbers */ 48 44 #define NAME_HASH_PRIME 16381 49 static char *name_hashtable[NAME_HASH_PRIME + 1];50 45 51 46 /* PACKAGE_HASH_PRIME, Maximum number of unique packages, … … 59 54 #define PACKAGE_HASH_PRIME 10007 60 55 typedef struct edge_s { 61 unsigned int operator:3;62 unsigned inttype:4;63 unsigned int name:14;64 unsigned int version:14;56 unsigned operator:4; /* was:3 */ 57 unsigned type:4; 58 unsigned name:16; /* was:14 */ 59 unsigned version:16; /* was:14 */ 65 60 } edge_t; 66 61 67 62 typedef struct common_node_s { 68 unsigned int name:14;69 unsigned int version:14;70 unsigned int num_of_edges:14;63 unsigned name:16; /* was:14 */ 64 unsigned version:16; /* was:14 */ 65 unsigned num_of_edges:16; /* was:14 */ 71 66 edge_t **edge; 72 67 } common_node_t; 73 static common_node_t *package_hashtable[PACKAGE_HASH_PRIME + 1];74 68 75 69 /* Currently it doesnt store packages that have state-status of not-installed … … 78 72 #define STATUS_HASH_PRIME 8191 79 73 typedef struct status_node_s { 80 unsigned int package:14;/* has to fit PACKAGE_HASH_PRIME */81 unsigned int status:14;/* has to fit STATUS_HASH_PRIME */74 unsigned package:16; /* was:14 */ /* has to fit PACKAGE_HASH_PRIME */ 75 unsigned status:16; /* was:14 */ /* has to fit STATUS_HASH_PRIME */ 82 76 } status_node_t; 83 static status_node_t *status_hashtable[STATUS_HASH_PRIME + 1]; 77 78 /* Were statically declared here, but such a big bss is nommu-unfriendly */ 79 static char **name_hashtable; /* [NAME_HASH_PRIME + 1] */ 80 static common_node_t **package_hashtable; /* [PACKAGE_HASH_PRIME + 1] */ 81 static status_node_t **status_hashtable; /* [STATUS_HASH_PRIME + 1] */ 84 82 85 83 /* Even numbers are for 'extras', like ored dependencies or null */ … … 107 105 }; 108 106 109 enum dpkg_opt_e {110 dpkg_opt_purge = 1,111 dpkg_opt_remove = 2,112 dpkg_opt_unpack = 4,113 dpkg_opt_configure = 8,114 dpkg_opt_install = 16,115 dpkg_opt_package_name = 32,116 dpkg_opt_filename = 64,117 dpkg_opt_list_installed = 128,118 dpkg_opt_force_ignore_depends = 256119 };120 121 107 typedef struct deb_file_s { 122 108 char *control_file; 123 109 char *filename; 124 unsigned int package:14;110 unsigned package:16; /* was:14 */ 125 111 } deb_file_t; 126 112 127 113 128 static void make_hash(const char *key, unsigned int *start, unsigned int*decrement, const int hash_prime)129 { 130 unsigned long inthash_num = key[0];114 static void make_hash(const char *key, unsigned *start, unsigned *decrement, const int hash_prime) 115 { 116 unsigned long hash_num = key[0]; 131 117 int len = strlen(key); 132 118 int i; … … 134 120 /* Maybe i should have uses a "proper" hashing algorithm here instead 135 121 * of making one up myself, seems to be working ok though. */ 136 for (i = 1; i < len; i++) {122 for (i = 1; i < len; i++) { 137 123 /* shifts the ascii based value and adds it to previous value 138 124 * shift amount is mod 24 because long int is 32 bit and data … … 141 127 hash_num += ((key[i] + key[i-1]) << ((key[i] * i) % 24)); 142 128 } 143 *start = (unsigned int) hash_num % hash_prime;144 *decrement = (unsigned int) 1 + (hash_num % (hash_prime - 1));129 *start = (unsigned) hash_num % hash_prime; 130 *decrement = (unsigned) 1 + (hash_num % (hash_prime - 1)); 145 131 } 146 132 … … 148 134 static int search_name_hashtable(const char *key) 149 135 { 150 unsigned int probe_address = 0; 151 unsigned int probe_decrement = 0; 152 // char *temp; 136 unsigned probe_address = 0; 137 unsigned probe_decrement = 0; 153 138 154 139 make_hash(key, &probe_address, &probe_decrement, NAME_HASH_PRIME); 155 while (name_hashtable[probe_address] != NULL) {140 while (name_hashtable[probe_address] != NULL) { 156 141 if (strcmp(name_hashtable[probe_address], key) == 0) { 157 return(probe_address); 158 } else { 159 probe_address -= probe_decrement; 160 if ((int)probe_address < 0) { 161 probe_address += NAME_HASH_PRIME; 162 } 163 } 164 } 165 name_hashtable[probe_address] = bb_xstrdup(key); 166 return(probe_address); 142 return probe_address; 143 } 144 probe_address -= probe_decrement; 145 if ((int)probe_address < 0) { 146 probe_address += NAME_HASH_PRIME; 147 } 148 } 149 name_hashtable[probe_address] = xstrdup(key); 150 return probe_address; 167 151 } 168 152 … … 170 154 * TODO make it consistent with search_name_hashtable 171 155 */ 172 static unsigned intsearch_status_hashtable(const char *key)173 { 174 unsigned intprobe_address = 0;175 unsigned intprobe_decrement = 0;156 static unsigned search_status_hashtable(const char *key) 157 { 158 unsigned probe_address = 0; 159 unsigned probe_decrement = 0; 176 160 177 161 make_hash(key, &probe_address, &probe_decrement, STATUS_HASH_PRIME); 178 while (status_hashtable[probe_address] != NULL) {162 while (status_hashtable[probe_address] != NULL) { 179 163 if (strcmp(key, name_hashtable[package_hashtable[status_hashtable[probe_address]->package]->name]) == 0) { 180 164 break; 181 } else { 182 probe_address -= probe_decrement; 183 if ((int)probe_address < 0) { 184 probe_address += STATUS_HASH_PRIME; 185 } 186 } 187 } 188 return(probe_address); 165 } 166 probe_address -= probe_decrement; 167 if ((int)probe_address < 0) { 168 probe_address += STATUS_HASH_PRIME; 169 } 170 } 171 return probe_address; 189 172 } 190 173 … … 201 184 int ver_num1; 202 185 int ver_num2; 203 int ret;204 186 205 187 if (version1 == NULL) { 206 version1 = bb_xstrdup("");188 version1 = xstrdup(""); 207 189 } 208 190 if (version2 == NULL) { 209 version2 = bb_xstrdup("");191 version2 = xstrdup(""); 210 192 } 211 193 upstream_len1 = strlen(version1); … … 215 197 /* Compare non-digit section */ 216 198 tmp_int = strcspn(&version1[len1], "0123456789"); 217 name1_char = bb_xstrndup(&version1[len1], tmp_int);199 name1_char = xstrndup(&version1[len1], tmp_int); 218 200 len1 += tmp_int; 219 201 tmp_int = strcspn(&version2[len2], "0123456789"); 220 name2_char = bb_xstrndup(&version2[len2], tmp_int);202 name2_char = xstrndup(&version2[len2], tmp_int); 221 203 len2 += tmp_int; 222 204 tmp_int = strcmp(name1_char, name2_char); … … 224 206 free(name2_char); 225 207 if (tmp_int != 0) { 226 ret = tmp_int; 227 goto cleanup_version_compare_part; 208 return tmp_int; 228 209 } 229 210 230 211 /* Compare digits */ 231 212 tmp_int = strspn(&version1[len1], "0123456789"); 232 name1_char = bb_xstrndup(&version1[len1], tmp_int);213 name1_char = xstrndup(&version1[len1], tmp_int); 233 214 len1 += tmp_int; 234 215 tmp_int = strspn(&version2[len2], "0123456789"); 235 name2_char = bb_xstrndup(&version2[len2], tmp_int);216 name2_char = xstrndup(&version2[len2], tmp_int); 236 217 len2 += tmp_int; 237 218 ver_num1 = atoi(name1_char); … … 240 221 free(name2_char); 241 222 if (ver_num1 < ver_num2) { 242 ret = -1; 243 goto cleanup_version_compare_part; 244 } 245 else if (ver_num1 > ver_num2) { 246 ret = 1; 247 goto cleanup_version_compare_part; 248 } 249 } 250 ret = 0; 251 cleanup_version_compare_part: 252 return(ret); 223 return -1; 224 } 225 if (ver_num1 > ver_num2) { 226 return 1; 227 } 228 } 229 return 0; 253 230 } 254 231 … … 257 234 * if ver1 > ver2 return 1, 258 235 */ 259 static int version_compare(const unsigned int ver1, const unsigned intver2)236 static int version_compare(const unsigned ver1, const unsigned ver2) 260 237 { 261 238 char *ch_ver1 = name_hashtable[ver1]; … … 285 262 } 286 263 if (epoch1 < epoch2) { 287 return (-1);264 return -1; 288 265 } 289 266 else if (epoch1 > epoch2) { 290 return (1);267 return 1; 291 268 } 292 269 293 270 /* Compare upstream version */ 294 upstream_ver1 = bb_xstrdup(ver1_ptr);295 upstream_ver2 = bb_xstrdup(ver2_ptr);271 upstream_ver1 = xstrdup(ver1_ptr); 272 upstream_ver2 = xstrdup(ver2_ptr); 296 273 297 274 /* Chop off debian version, and store for later use */ … … 307 284 } 308 285 result = version_compare_part(upstream_ver1, upstream_ver2); 286 if (!result) 287 /* Compare debian versions */ 288 result = version_compare_part(deb_ver1, deb_ver2); 309 289 310 290 free(upstream_ver1); 311 291 free(upstream_ver2); 312 313 if (result != 0) { 314 return(result); 315 } 316 317 /* Compare debian versions */ 318 return(version_compare_part(deb_ver1, deb_ver2)); 319 } 320 321 static int test_version(const unsigned int version1, const unsigned int version2, const unsigned int operator) 292 return result; 293 } 294 295 static int test_version(const unsigned version1, const unsigned version2, const unsigned operator) 322 296 { 323 297 const int version_result = version_compare(version1, version2); 324 switch(operator) { 325 case (VER_ANY): 326 return(TRUE); 327 case (VER_EQUAL): 328 if (version_result == 0) { 329 return(TRUE); 330 } 331 break; 332 case (VER_LESS): 333 if (version_result < 0) { 334 return(TRUE); 335 } 336 break; 337 case (VER_LESS_EQUAL): 338 if (version_result <= 0) { 339 return(TRUE); 340 } 341 break; 342 case (VER_MORE): 343 if (version_result > 0) { 344 return(TRUE); 345 } 346 break; 347 case (VER_MORE_EQUAL): 348 if (version_result >= 0) { 349 return(TRUE); 350 } 351 break; 352 } 353 return(FALSE); 354 } 355 356 357 static int search_package_hashtable(const unsigned int name, const unsigned int version, const unsigned int operator) 358 { 359 unsigned int probe_address = 0; 360 unsigned int probe_decrement = 0; 298 switch (operator) { 299 case VER_ANY: 300 return TRUE; 301 case VER_EQUAL: 302 return (version_result == 0); 303 case VER_LESS: 304 return (version_result < 0); 305 case VER_LESS_EQUAL: 306 return (version_result <= 0); 307 case VER_MORE: 308 return (version_result > 0); 309 case VER_MORE_EQUAL: 310 return (version_result >= 0); 311 } 312 return FALSE; 313 } 314 315 316 static int search_package_hashtable(const unsigned name, const unsigned version, const unsigned operator) 317 { 318 unsigned probe_address = 0; 319 unsigned probe_decrement = 0; 361 320 362 321 make_hash(name_hashtable[name], &probe_address, &probe_decrement, PACKAGE_HASH_PRIME); 363 while (package_hashtable[probe_address] != NULL) {322 while (package_hashtable[probe_address] != NULL) { 364 323 if (package_hashtable[probe_address]->name == name) { 365 324 if (operator == VER_ANY) { 366 return (probe_address);325 return probe_address; 367 326 } 368 327 if (test_version(package_hashtable[probe_address]->version, version, operator)) { 369 return (probe_address);328 return probe_address; 370 329 } 371 330 } … … 375 334 } 376 335 } 377 return (probe_address);336 return probe_address; 378 337 } 379 338 … … 394 353 * it simple for now until it proves to be a problem. 395 354 */ 396 static int search_for_provides(int needle, int start_at) { 355 static int search_for_provides(int needle, int start_at) 356 { 397 357 int i, j; 398 358 common_node_t *p; 399 359 for (i = start_at + 1; i < PACKAGE_HASH_PRIME; i++) { 400 360 p = package_hashtable[i]; 401 if ( p == NULL ) continue; 402 for(j = 0; j < p->num_of_edges; j++) 403 if ( p->edge[j]->type == EDGE_PROVIDES && p->edge[j]->name == needle ) 361 if (p == NULL) 362 continue; 363 for (j = 0; j < p->num_of_edges; j++) 364 if (p->edge[j]->type == EDGE_PROVIDES && p->edge[j]->name == needle) 404 365 return i; 405 366 } … … 427 388 * this alternative. 428 389 */ 429 static void add_split_dependencies(common_node_t *parent_node, const char *whole_line, unsigned intedge_type)430 { 431 char *line = bb_xstrdup(whole_line);390 static void add_split_dependencies(common_node_t *parent_node, const char *whole_line, unsigned edge_type) 391 { 392 char *line = xstrdup(whole_line); 432 393 char *line2; 433 394 char *line_ptr1 = NULL; … … 444 405 /* skip leading spaces */ 445 406 field += strspn(field, " "); 446 line2 = bb_xstrdup(field);407 line2 = xstrdup(field); 447 408 field2 = strtok_r(line2, "|", &line_ptr2); 448 if ( (edge_type == EDGE_DEPENDS || edge_type == EDGE_PRE_DEPENDS) && 449 (strcmp(field, field2) != 0)) { 450 or_edge = (edge_t *)xmalloc(sizeof(edge_t)); 409 or_edge = NULL; 410 if ((edge_type == EDGE_DEPENDS || edge_type == EDGE_PRE_DEPENDS) 411 && (strcmp(field, field2) != 0) 412 ) { 413 or_edge = xmalloc(sizeof(edge_t)); 451 414 or_edge->type = edge_type + 1; 452 } else {453 or_edge = NULL;454 }455 456 if ( or_edge ) {457 415 or_edge->name = search_name_hashtable(field); 458 or_edge->version = 0; // tracks the number of altenatives 459 416 or_edge->version = 0; // tracks the number of alternatives 460 417 add_edge_to_node(parent_node, or_edge); 461 418 } 462 419 463 420 do { 464 edge = (edge_t *)xmalloc(sizeof(edge_t));421 edge = xmalloc(sizeof(edge_t)); 465 422 edge->type = edge_type; 466 423 … … 476 433 } else { 477 434 /* Skip leading ' ' or '(' */ 478 version += strspn(field2, " "); 479 version += strspn(version, "("); 435 version += strspn(version, " ("); 480 436 /* Calculate length of any operator characters */ 481 437 offset_ch = strspn(version, "<=>"); … … 497 453 edge->operator = VER_MORE_EQUAL; 498 454 } else { 499 bb_error_msg_and_die(" Illegal operator\n");455 bb_error_msg_and_die("illegal operator"); 500 456 } 501 457 } … … 514 470 edge->name = search_name_hashtable(field2); 515 471 516 if ( or_edge)472 if (or_edge) 517 473 or_edge->version++; 518 474 519 475 add_edge_to_node(parent_node, edge); 520 } while ((field2 = strtok_r(NULL, "|", &line_ptr2)) != NULL); 476 field2 = strtok_r(NULL, "|", &line_ptr2); 477 } while (field2 != NULL); 478 521 479 free(line2); 522 } while ((field = strtok_r(NULL, ",", &line_ptr1)) != NULL); 480 field = strtok_r(NULL, ",", &line_ptr1); 481 } while (field != NULL); 482 523 483 free(line); 524 525 return;526 484 } 527 485 528 486 static void free_package(common_node_t *node) 529 487 { 530 unsigned shorti;488 unsigned i; 531 489 if (node) { 532 490 for (i = 0; i < node->num_of_edges; i++) { … … 538 496 } 539 497 540 static unsigned int fill_package_struct(char *control_buffer) 541 { 542 static const char *const field_names[] = { "Package", "Version", 543 "Pre-Depends", "Depends","Replaces", "Provides", 544 "Conflicts", "Suggests", "Recommends", "Enhances", 0 545 }; 546 547 common_node_t *new_node = (common_node_t *) xzalloc(sizeof(common_node_t)); 498 /* 499 * Gets the next package field from package_buffer, seperated into the field name 500 * and field value, it returns the int offset to the first character of the next field 501 */ 502 static int read_package_field(const char *package_buffer, char **field_name, char **field_value) 503 { 504 int offset_name_start = 0; 505 int offset_name_end = 0; 506 int offset_value_start = 0; 507 int offset_value_end = 0; 508 int offset = 0; 509 int next_offset; 510 int name_length; 511 int value_length; 512 int exit_flag = FALSE; 513 514 if (package_buffer == NULL) { 515 *field_name = NULL; 516 *field_value = NULL; 517 return -1; 518 } 519 while (1) { 520 next_offset = offset + 1; 521 switch (package_buffer[offset]) { 522 case '\0': 523 exit_flag = TRUE; 524 break; 525 case ':': 526 if (offset_name_end == 0) { 527 offset_name_end = offset; 528 offset_value_start = next_offset; 529 } 530 /* TODO: Name might still have trailing spaces if ':' isnt 531 * immediately after name */ 532 break; 533 case '\n': 534 /* TODO: The char next_offset may be out of bounds */ 535 if (package_buffer[next_offset] != ' ') { 536 exit_flag = TRUE; 537 break; 538 } 539 case '\t': 540 case ' ': 541 /* increment the value start point if its a just filler */ 542 if (offset_name_start == offset) { 543 offset_name_start++; 544 } 545 if (offset_value_start == offset) { 546 offset_value_start++; 547 } 548 break; 549 } 550 if (exit_flag) { 551 /* Check that the names are valid */ 552 offset_value_end = offset; 553 name_length = offset_name_end - offset_name_start; 554 value_length = offset_value_end - offset_value_start; 555 if (name_length == 0) { 556 break; 557 } 558 if ((name_length > 0) && (value_length > 0)) { 559 break; 560 } 561 562 /* If not valid, start fresh with next field */ 563 exit_flag = FALSE; 564 offset_name_start = offset + 1; 565 offset_name_end = 0; 566 offset_value_start = offset + 1; 567 offset_value_end = offset + 1; 568 offset++; 569 } 570 offset++; 571 } 572 *field_name = NULL; 573 if (name_length) { 574 *field_name = xstrndup(&package_buffer[offset_name_start], name_length); 575 } 576 *field_value = NULL; 577 if (value_length > 0) { 578 *field_value = xstrndup(&package_buffer[offset_value_start], value_length); 579 } 580 return next_offset; 581 } 582 583 static unsigned fill_package_struct(char *control_buffer) 584 { 585 static const char field_names[] ALIGN1 = 586 "Package\0""Version\0" 587 "Pre-Depends\0""Depends\0""Replaces\0""Provides\0" 588 "Conflicts\0""Suggests\0""Recommends\0""Enhances\0"; 589 590 common_node_t *new_node = xzalloc(sizeof(common_node_t)); 548 591 char *field_name; 549 592 char *field_value; … … 554 597 new_node->version = search_name_hashtable("unknown"); 555 598 while (field_start < buffer_length) { 556 unsigned shortfield_num;599 unsigned field_num; 557 600 558 601 field_start += read_package_field(&control_buffer[field_start], … … 560 603 561 604 if (field_name == NULL) { 562 goto fill_package_struct_cleanup; /* Oh no, the dreaded goto statement 563 } 564 565 field_num = compare_string_array(field_names, field_name);566 switch (field_num) {567 568 569 570 571 572 573 574 575 576 577 578 579 580 581 582 583 584 585 586 587 588 589 590 591 592 593 594 595 596 597 } 598 fill_package_struct_cleanup:605 goto fill_package_struct_cleanup; /* Oh no, the dreaded goto statement! */ 606 } 607 608 field_num = index_in_strings(field_names, field_name); 609 switch (field_num) { 610 case 0: /* Package */ 611 new_node->name = search_name_hashtable(field_value); 612 break; 613 case 1: /* Version */ 614 new_node->version = search_name_hashtable(field_value); 615 break; 616 case 2: /* Pre-Depends */ 617 add_split_dependencies(new_node, field_value, EDGE_PRE_DEPENDS); 618 break; 619 case 3: /* Depends */ 620 add_split_dependencies(new_node, field_value, EDGE_DEPENDS); 621 break; 622 case 4: /* Replaces */ 623 add_split_dependencies(new_node, field_value, EDGE_REPLACES); 624 break; 625 case 5: /* Provides */ 626 add_split_dependencies(new_node, field_value, EDGE_PROVIDES); 627 break; 628 case 6: /* Conflicts */ 629 add_split_dependencies(new_node, field_value, EDGE_CONFLICTS); 630 break; 631 case 7: /* Suggests */ 632 add_split_dependencies(new_node, field_value, EDGE_SUGGESTS); 633 break; 634 case 8: /* Recommends */ 635 add_split_dependencies(new_node, field_value, EDGE_RECOMMENDS); 636 break; 637 case 9: /* Enhances */ 638 add_split_dependencies(new_node, field_value, EDGE_ENHANCES); 639 break; 640 } 641 fill_package_struct_cleanup: 599 642 free(field_name); 600 643 free(field_value); … … 603 646 if (new_node->version == search_name_hashtable("unknown")) { 604 647 free_package(new_node); 605 return (-1);648 return -1; 606 649 } 607 650 num = search_package_hashtable(new_node->name, new_node->version, VER_EQUAL); 608 if (package_hashtable[num] == NULL) { 609 package_hashtable[num] = new_node; 610 } else { 611 free_package(new_node); 612 } 613 return(num); 651 free_package(package_hashtable[num]); 652 package_hashtable[num] = new_node; 653 return num; 614 654 } 615 655 616 656 /* if num = 1, it returns the want status, 2 returns flag, 3 returns status */ 617 static unsigned int get_status(const unsigned intstatus_node, const int num)657 static unsigned get_status(const unsigned status_node, const int num) 618 658 { 619 659 char *status_string = name_hashtable[status_hashtable[status_node]->status]; 620 660 char *state_sub_string; 621 unsigned intstate_sub_num;661 unsigned state_sub_num; 622 662 int len; 623 663 int i; … … 630 670 status_string += strspn(status_string, " "); 631 671 } 632 len = strcspn(status_string, " \n \0");633 state_sub_string = bb_xstrndup(status_string, len);672 len = strcspn(status_string, " \n"); 673 state_sub_string = xstrndup(status_string, len); 634 674 state_sub_num = search_name_hashtable(state_sub_string); 635 675 free(state_sub_string); 636 return (state_sub_num);637 } 638 639 static void set_status(const unsigned intstatus_node_num, const char *new_value, const int position)640 { 641 const unsigned intnew_value_len = strlen(new_value);642 const unsigned intnew_value_num = search_name_hashtable(new_value);643 unsigned intwant = get_status(status_node_num, 1);644 unsigned intflag = get_status(status_node_num, 2);645 unsigned intstatus = get_status(status_node_num, 3);676 return state_sub_num; 677 } 678 679 static void set_status(const unsigned status_node_num, const char *new_value, const int position) 680 { 681 const unsigned new_value_len = strlen(new_value); 682 const unsigned new_value_num = search_name_hashtable(new_value); 683 unsigned want = get_status(status_node_num, 1); 684 unsigned flag = get_status(status_node_num, 2); 685 unsigned status = get_status(status_node_num, 3); 646 686 int want_len = strlen(name_hashtable[want]); 647 687 int flag_len = strlen(name_hashtable[flag]); … … 650 690 651 691 switch (position) { 652 case (1):692 case 1: 653 693 want = new_value_num; 654 694 want_len = new_value_len; 655 695 break; 656 case (2):696 case 2: 657 697 flag = new_value_num; 658 698 flag_len = new_value_len; 659 699 break; 660 case (3):700 case 3: 661 701 status = new_value_num; 662 702 status_len = new_value_len; … … 666 706 } 667 707 668 new_status = bb_xasprintf("%s %s %s", name_hashtable[want], name_hashtable[flag], name_hashtable[status]);708 new_status = xasprintf("%s %s %s", name_hashtable[want], name_hashtable[flag], name_hashtable[status]); 669 709 status_hashtable[status_node_num]->status = search_name_hashtable(new_status); 670 710 free(new_status); 671 return; 672 } 673 674 static const char *describe_status(int status_num){675 int status_want, status_state 676 if ( status_hashtable[status_num] == NULL || status_hashtable[status_num]->status == 0)677 return "is not installed or flagged to be installed \n";711 } 712 713 static const char *describe_status(int status_num) 714 { 715 int status_want, status_state; 716 if (status_hashtable[status_num] == NULL || status_hashtable[status_num]->status == 0) 717 return "is not installed or flagged to be installed"; 678 718 679 719 status_want = get_status(status_num, 1); 680 720 status_state = get_status(status_num, 3); 681 721 682 if ( status_state == search_name_hashtable("installed")) {683 if ( status_want == search_name_hashtable("install"))722 if (status_state == search_name_hashtable("installed")) { 723 if (status_want == search_name_hashtable("install")) 684 724 return "is installed"; 685 if ( status_want == search_name_hashtable("deinstall"))725 if (status_want == search_name_hashtable("deinstall")) 686 726 return "is marked to be removed"; 687 if ( status_want == search_name_hashtable("purge"))727 if (status_want == search_name_hashtable("purge")) 688 728 return "is marked to be purged"; 689 729 } 690 if ( status_want == search_name_hashtable("unknown"))730 if (status_want == search_name_hashtable("unknown")) 691 731 return "is in an indeterminate state"; 692 if ( status_want == search_name_hashtable("install"))732 if (status_want == search_name_hashtable("install")) 693 733 return "is marked to be installed"; 694 734 … … 703 743 char *status_line; 704 744 status_node_t *status_node = NULL; 705 unsigned intstatus_num;706 707 status_file = bb_xfopen(filename, "r");708 while ((control_buffer = fgets_str(status_file, "\n\n")) != NULL) {709 const unsigned intpackage_num = fill_package_struct(control_buffer);745 unsigned status_num; 746 747 status_file = xfopen(filename, "r"); 748 while ((control_buffer = xmalloc_fgets_str(status_file, "\n\n")) != NULL) { 749 const unsigned package_num = fill_package_struct(control_buffer); 710 750 if (package_num != -1) { 711 751 status_node = xmalloc(sizeof(status_node_t)); … … 715 755 status_line += 7; 716 756 status_line += strspn(status_line, " \n\t"); 717 status_line = bb_xstrndup(status_line, strcspn(status_line, "\n\0"));757 status_line = xstrndup(status_line, strcspn(status_line, "\n")); 718 758 status_node->status = search_name_hashtable(status_line); 719 759 free(status_line); … … 726 766 } 727 767 fclose(status_file); 728 return;729 768 } 730 769 … … 743 782 } 744 783 } 745 return;746 784 } 747 785 … … 749 787 static void write_status_file(deb_file_t **deb_file) 750 788 { 751 FILE *old_status_file = bb_xfopen("/var/lib/dpkg/status", "r");752 FILE *new_status_file = bb_xfopen("/var/lib/dpkg/status.udeb", "w");789 FILE *old_status_file = xfopen("/var/lib/dpkg/status", "r"); 790 FILE *new_status_file = xfopen("/var/lib/dpkg/status.udeb", "w"); 753 791 char *package_name; 754 792 char *status_from_file; … … 761 799 762 800 /* Update previously known packages */ 763 while ((control_buffer = fgets_str(old_status_file, "\n\n")) != NULL) { 764 if ((tmp_string = strstr(control_buffer, "Package:")) == NULL) { 801 while ((control_buffer = xmalloc_fgets_str(old_status_file, "\n\n")) != NULL) { 802 tmp_string = strstr(control_buffer, "Package:"); 803 if (tmp_string == NULL) { 765 804 continue; 766 805 } … … 768 807 tmp_string += 8; 769 808 tmp_string += strspn(tmp_string, " \n\t"); 770 package_name = bb_xstrndup(tmp_string, strcspn(tmp_string, "\n\0"));809 package_name = xstrndup(tmp_string, strcspn(tmp_string, "\n")); 771 810 write_flag = FALSE; 772 811 tmp_string = strstr(control_buffer, "Status:"); … … 775 814 tmp_string += 7; 776 815 tmp_string += strspn(tmp_string, " \n\t"); 777 status_from_file = bb_xstrndup(tmp_string, strcspn(tmp_string, "\n"));816 status_from_file = xstrndup(tmp_string, strcspn(tmp_string, "\n")); 778 817 } else { 779 818 status_from_file = NULL; … … 787 826 /* New status isnt exactly the same as old status */ 788 827 const int state_status = get_status(status_num, 3); 789 if ((strcmp("installed", name_hashtable[state_status]) == 0) || 790 (strcmp("unpacked", name_hashtable[state_status]) == 0)) { 828 if ((strcmp("installed", name_hashtable[state_status]) == 0) 829 || (strcmp("unpacked", name_hashtable[state_status]) == 0) 830 ) { 791 831 /* We need to add the control file from the package */ 792 832 i = 0; 793 while (deb_file[i] != NULL) {833 while (deb_file[i] != NULL) { 794 834 if (strcmp(package_name, name_hashtable[package_hashtable[deb_file[i]->package]->name]) == 0) { 795 835 /* Write a status file entry with a modified status */ … … 797 837 write_buffer_no_status(new_status_file, deb_file[i]->control_file); 798 838 set_status(status_num, "ok", 2); 799 fprintf(new_status_file, "Status: %s\n\n", name_hashtable[status_hashtable[status_num]->status]); 839 fprintf(new_status_file, "Status: %s\n\n", 840 name_hashtable[status_hashtable[status_num]->status]); 800 841 write_flag = TRUE; 801 842 break; … … 805 846 /* This is temperary, debugging only */ 806 847 if (deb_file[i] == NULL) { 807 bb_error_msg_and_die("ALERT: Couldnt find a control file, your status file may be broken, status may be incorrect for %s", package_name); 848 bb_error_msg_and_die("ALERT: cannot find a control file, " 849 "your status file may be broken, status may be " 850 "incorrect for %s", package_name); 808 851 } 809 852 } … … 850 893 } 851 894 /* If the package from the status file wasnt handle above, do it now*/ 852 if (! 895 if (!write_flag) { 853 896 fprintf(new_status_file, "%s\n\n", control_buffer); 854 897 } … … 860 903 861 904 /* Write any new packages */ 862 for (i = 0; deb_file[i] != NULL; i++) {905 for (i = 0; deb_file[i] != NULL; i++) { 863 906 status_num = search_status_hashtable(name_hashtable[package_hashtable[deb_file[i]->package]->name]); 864 907 if (strcmp("reinstreq", name_hashtable[get_status(status_num, 2)]) == 0) { … … 878 921 /* Its ok if renaming the status file fails because status 879 922 * file doesnt exist, maybe we are starting from scratch */ 880 bb_error_msg(" No status file found, creating new one");923 bb_error_msg("no status file found, creating new one"); 881 924 } 882 925 883 926 if (rename("/var/lib/dpkg/status.udeb", "/var/lib/dpkg/status") == -1) { 884 bb_error_msg_and_die("DANGER: Couldnt create status file, you need to manually repair your status file"); 927 bb_error_msg_and_die("DANGER: cannot create status file, " 928 "you need to manually repair your status file"); 885 929 } 886 930 } … … 900 944 * provides which cannot satisfy any dependency by itself. 901 945 */ 902 if ( status_hashtable[status_num] == NULL)946 if (status_hashtable[status_num] == NULL) 903 947 return 0; 904 948 … … 927 971 * installed package for conflicts*/ 928 972 while (deb_file[i] != NULL) { 929 const unsigned intpackage_num = deb_file[i]->package;973 const unsigned package_num = deb_file[i]->package; 930 974 conflicts = xrealloc(conflicts, sizeof(int) * (conflicts_num + 1)); 931 975 conflicts[conflicts_num] = package_num; … … 940 984 if (package_hashtable[conflicts_package_num] == NULL) { 941 985 /* create a new package */ 942 common_node_t *new_node = (common_node_t *)xzalloc(sizeof(common_node_t));986 common_node_t *new_node = xzalloc(sizeof(common_node_t)); 943 987 new_node->name = package_hashtable[package_num]->edge[j]->name; 944 988 new_node->version = package_hashtable[package_num]->edge[j]->version; … … 969 1013 970 1014 if (package_edge->type == EDGE_CONFLICTS) { 971 const unsigned intpackage_num =1015 const unsigned package_num = 972 1016 search_package_hashtable(package_edge->name, 973 1017 package_edge->version, … … 984 1028 985 1029 if (result) { 986 bb_error_msg_and_die(" Package %s conflicts with %s",1030 bb_error_msg_and_die("package %s conflicts with %s", 987 1031 name_hashtable[package_node->name], 988 1032 name_hashtable[package_edge->name]); … … 1005 1049 * no dependencies to check. 1006 1050 */ 1007 if ( package_node == NULL) continue;1051 if (package_node == NULL) continue; 1008 1052 1009 1053 status_num = search_status_hashtable(name_hashtable[package_node->name]); … … 1013 1057 * case there are no dependencies to check. 1014 1058 */ 1015 if ( status_hashtable[status_num] == NULL) continue;1059 if (status_hashtable[status_num] == NULL) continue; 1016 1060 1017 1061 /* If we don't want this package installed then we may … … 1021 1065 continue; 1022 1066 } 1023 1024 #if 01025 /* This might be needed so we don't complain about1026 * things which are broken but unrelated to the1027 * packages that are currently being installed1028 */1029 if (state_status == search_name_hashtable("installed"))1030 continue;1031 #endif1032 1067 1033 1068 /* This code is tested only for EDGE_DEPENDS, since I … … 1037 1072 for (j = 0; j < package_node->num_of_edges; j++) { 1038 1073 const edge_t *package_edge = package_node->edge[j]; 1039 unsigned int package_num; 1040 1041 if ( package_edge->type == EDGE_OR_PRE_DEPENDS || 1042 package_edge->type == EDGE_OR_DEPENDS ) { /* start an EDGE_OR_ list */ 1074 unsigned package_num; 1075 1076 if (package_edge->type == EDGE_OR_PRE_DEPENDS 1077 || package_edge->type == EDGE_OR_DEPENDS 1078 ) { /* start an EDGE_OR_ list */ 1043 1079 number_of_alternatives = package_edge->version; 1044 1080 root_of_alternatives = package_edge; 1045 1081 continue; 1046 } else if ( number_of_alternatives == 0 ) { /* not in the middle of an EDGE_OR_ list */ 1082 } 1083 if (number_of_alternatives == 0) { /* not in the middle of an EDGE_OR_ list */ 1047 1084 number_of_alternatives = 1; 1048 1085 root_of_alternatives = NULL; … … 1052 1089 1053 1090 if (package_edge->type == EDGE_PRE_DEPENDS || 1054 package_edge->type == EDGE_DEPENDS 1091 package_edge->type == EDGE_DEPENDS) { 1055 1092 int result=1; 1056 1093 status_num = 0; … … 1062 1099 * EDGE_PRE_DEPENDS == OR_PRE_DEPENDS -1 1063 1100 */ 1064 if ( 1065 bb_error_msg_and_die(" Fatal error. Package dependencies corrupt: %d != %d - 1 \n",1101 if (root_of_alternatives && package_edge->type != root_of_alternatives->type - 1) 1102 bb_error_msg_and_die("fatal error, package dependencies corrupt: %d != %d - 1", 1066 1103 package_edge->type, root_of_alternatives->type); 1067 1104 … … 1072 1109 int provider = -1; 1073 1110 1074 while ( (provider = search_for_provides(package_edge->name, provider) ) > -1) {1075 if ( package_hashtable[provider] == NULL) {1076 p rintf("Have a provider but no package information for it\n");1111 while ((provider = search_for_provides(package_edge->name, provider)) > -1) { 1112 if (package_hashtable[provider] == NULL) { 1113 puts("Have a provider but no package information for it"); 1077 1114 continue; 1078 1115 } 1079 1116 result = !package_satisfies_dependency(provider, package_edge->type); 1080 1117 1081 if ( result == 0)1118 if (result == 0) 1082 1119 break; 1083 1120 } … … 1087 1124 number_of_alternatives--; 1088 1125 if (result && number_of_alternatives == 0) { 1089 if ( root_of_alternatives)1126 if (root_of_alternatives) 1090 1127 bb_error_msg_and_die( 1091 " Package %s %sdepends on %s, "1128 "package %s %sdepends on %s, " 1092 1129 "which cannot be satisfied", 1093 1130 name_hashtable[package_node->name], 1094 1131 package_edge->type == EDGE_PRE_DEPENDS ? "pre-" : "", 1095 1132 name_hashtable[root_of_alternatives->name]); 1096 else1097 bb_error_msg_and_die(1098 "Package %s %sdepends on %s, which %s\n",1099 name_hashtable[package_node->name],1100 package_edge->type == EDGE_PRE_DEPENDS ? "pre-" : "",1101 name_hashtable[package_edge->name],1102 describe_status(status_num));1103 } else if ( result == 0 && number_of_alternatives) {1133 bb_error_msg_and_die( 1134 "package %s %sdepends on %s, which %s\n", 1135 name_hashtable[package_node->name], 1136 package_edge->type == EDGE_PRE_DEPENDS ? "pre-" : "", 1137 name_hashtable[package_edge->name], 1138 describe_status(status_num)); 1139 } 1140 if (result == 0 && number_of_alternatives) { 1104 1141 /* we've found a package which 1105 1142 * satisfies the dependency, … … 1114 1151 } 1115 1152 free(conflicts); 1116 return (TRUE);1153 return TRUE; 1117 1154 } 1118 1155 … … 1127 1164 list_stream = fopen(filename, "r"); 1128 1165 if (list_stream == NULL) { 1129 return (NULL);1130 } 1131 1132 while ((line = bb_get_chomped_line_from_file(list_stream)) != NULL) {1166 return NULL; 1167 } 1168 1169 while ((line = xmalloc_getline(list_stream)) != NULL) { 1133 1170 file_list = xrealloc(file_list, sizeof(char *) * (count + 2)); 1134 1171 file_list[count] = line; … … 1138 1175 1139 1176 if (count == 0) { 1140 return(NULL); 1141 } else { 1142 file_list[count] = NULL; 1143 return(file_list); 1144 } 1177 return NULL; 1178 } 1179 file_list[count] = NULL; 1180 return file_list; 1145 1181 } 1146 1182 … … 1149 1185 { 1150 1186 struct stat path_stat; 1151 int match_flag; 1152 int remove_flag = FALSE; 1153 int i,j; 1187 int remove_flag = 1; /* not removed anything yet */ 1188 int i, j; 1154 1189 1155 1190 if (remove_names == NULL) { 1156 return (FALSE);1191 return 0; 1157 1192 } 1158 1193 for (i = 0; remove_names[i] != NULL; i++) { 1159 match_flag = FALSE;1160 1194 if (exclude_names != NULL) { 1161 for (j = 0; exclude_names[j] != 0; j++) {1195 for (j = 0; exclude_names[j] != NULL; j++) { 1162 1196 if (strcmp(remove_names[i], exclude_names[j]) == 0) { 1163 match_flag = TRUE; 1164 break; 1197 goto skip; 1165 1198 } 1166 1199 } 1167 1200 } 1168 if (!match_flag) { 1169 if (lstat(remove_names[i], &path_stat) < 0) { 1170 continue; 1171 } 1172 if (S_ISDIR(path_stat.st_mode)) { 1173 if (rmdir(remove_names[i]) != -1) { 1174 remove_flag = TRUE; 1175 } 1176 } else { 1177 if (unlink(remove_names[i]) != -1) { 1178 remove_flag = TRUE; 1179 } 1180 } 1181 } 1182 } 1183 return(remove_flag); 1201 /* TODO: why we are checking lstat? we can just try rm/rmdir */ 1202 if (lstat(remove_names[i], &path_stat) < 0) { 1203 continue; 1204 } 1205 if (S_ISDIR(path_stat.st_mode)) { 1206 remove_flag &= rmdir(remove_names[i]); /* 0 if no error */ 1207 } else { 1208 remove_flag &= unlink(remove_names[i]); /* 0 if no error */ 1209 } 1210 skip: 1211 continue; 1212 } 1213 return (remove_flag == 0); 1184 1214 } 1185 1215 … … 1190 1220 int result; 1191 1221 1192 script_path = bb_xasprintf("/var/lib/dpkg/info/%s.%s", package_name, script_type);1222 script_path = xasprintf("/var/lib/dpkg/info/%s.%s", package_name, script_type); 1193 1223 1194 1224 /* If the file doesnt exist is isnt a fatal */ 1195 1225 result = lstat(script_path, &path_stat) < 0 ? EXIT_SUCCESS : system(script_path); 1196 1226 free(script_path); 1197 return(result); 1198 } 1199 1200 static const char *all_control_files[] = {"preinst", "postinst", "prerm", "postrm", 1201 "list", "md5sums", "shlibs", "conffiles", "config", "templates", NULL }; 1227 return result; 1228 } 1229 1230 static const char *const all_control_files[] = { 1231 "preinst", "postinst", "prerm", "postrm", 1232 "list", "md5sums", "shlibs", "conffiles", 1233 "config", "templates", NULL 1234 }; 1202 1235 1203 1236 static char **all_control_list(const char *package_name) 1204 1237 { 1205 unsigned shorti = 0;1238 unsigned i = 0; 1206 1239 char **remove_files; 1207 1240 … … 1209 1242 remove_files = xzalloc(sizeof(all_control_files)); 1210 1243 while (all_control_files[i]) { 1211 remove_files[i] = bb_xasprintf("/var/lib/dpkg/info/%s.%s", package_name, all_control_files[i]);1244 remove_files[i] = xasprintf("/var/lib/dpkg/info/%s.%s", package_name, all_control_files[i]); 1212 1245 i++; 1213 1246 } 1214 1247 1215 return (remove_files);1248 return remove_files; 1216 1249 } 1217 1250 1218 1251 static void free_array(char **array) 1219 1252 { 1220 1221 1253 if (array) { 1222 unsigned shorti = 0;1254 unsigned i = 0; 1223 1255 while (array[i]) { 1224 1256 free(array[i]); … … 1237 1269 int i; 1238 1270 1239 p rintf(" Name Version\n");1240 p rintf("+++-==============-==============\n");1271 puts(" Name Version"); 1272 puts("+++-==============-=============="); 1241 1273 1242 1274 /* go through status hash, dereference package hash and finally strings */ 1243 for (i=0; i<STATUS_HASH_PRIME+1; i++) { 1244 1245 if (status_hashtable[i]) { 1246 const char *stat_str; /* status string */ 1275 for (i = 0; i < STATUS_HASH_PRIME+1; i++) { 1276 if (status_hashtable[i]) { 1277 const char *stat_str; /* status string */ 1247 1278 const char *name_str; /* package name */ 1248 1279 const char *vers_str; /* version */ … … 1259 1290 1260 1291 /* get abbreviation for status field 2 */ 1261 for (j =0, spccnt=0; stat_str[j] && spccnt<2; j++) {1262 1292 for (j = 0, spccnt = 0; stat_str[j] && spccnt < 2; j++) { 1293 if (stat_str[j] == ' ') spccnt++; 1263 1294 } 1264 1295 s2 = stat_str[j]; … … 1267 1298 printf("%c%c %-14s %s\n", s1, s2, name_str, vers_str); 1268 1299 } 1269 1270 } 1271 1272 static void remove_package(const unsigned intpackage_num, int noisy)1300 } 1301 } 1302 1303 static void remove_package(const unsigned package_num, int noisy) 1273 1304 { 1274 1305 const char *package_name = name_hashtable[package_hashtable[package_num]->name]; 1275 1306 const char *package_version = name_hashtable[package_hashtable[package_num]->version]; 1276 const unsigned intstatus_num = search_status_hashtable(package_name);1307 const unsigned status_num = search_status_hashtable(package_name); 1277 1308 const int package_name_length = strlen(package_name); 1278 1309 char **remove_files; … … 1280 1311 char list_name[package_name_length + 25]; 1281 1312 char conffile_name[package_name_length + 30]; 1282 int return_value; 1283 1284 if ( noisy ) 1285 printf("Removing %s (%s) ...\n", package_name, package_version); 1313 1314 if (noisy) 1315 printf("Removing %s (%s)...\n", package_name, package_version); 1286 1316 1287 1317 /* run prerm script */ 1288 return_value = run_package_script(package_name, "prerm"); 1289 if (return_value == -1) { 1318 if (run_package_script(package_name, "prerm") != 0) { 1290 1319 bb_error_msg_and_die("script failed, prerm failure"); 1291 1320 } … … 1298 1327 exclude_files = create_list(conffile_name); 1299 1328 1300 /* Some directories can t be removed straight away, so do multiple passes */1301 while (remove_file_array(remove_files, exclude_files)) ;1329 /* Some directories can't be removed straight away, so do multiple passes */ 1330 while (remove_file_array(remove_files, exclude_files)) /*repeat */; 1302 1331 free_array(exclude_files); 1303 1332 free_array(remove_files); … … 1305 1334 /* Create a list of files in /var/lib/dpkg/info/<package>.* to keep */ 1306 1335 exclude_files = xzalloc(sizeof(char*) * 3); 1307 exclude_files[0] = bb_xstrdup(conffile_name);1308 exclude_files[1] = bb_xasprintf("/var/lib/dpkg/info/%s.postrm", package_name);1336 exclude_files[0] = xstrdup(conffile_name); 1337 exclude_files[1] = xasprintf("/var/lib/dpkg/info/%s.postrm", package_name); 1309 1338 1310 1339 /* Create a list of all /var/lib/dpkg/info/<package> files */ … … 1322 1351 } 1323 1352 1324 static void purge_package(const unsigned intpackage_num)1353 static void purge_package(const unsigned package_num) 1325 1354 { 1326 1355 const char *package_name = name_hashtable[package_hashtable[package_num]->name]; 1327 1356 const char *package_version = name_hashtable[package_hashtable[package_num]->version]; 1328 const unsigned intstatus_num = search_status_hashtable(package_name);1357 const unsigned status_num = search_status_hashtable(package_name); 1329 1358 char **remove_files; 1330 1359 char **exclude_files; 1331 1360 char list_name[strlen(package_name) + 25]; 1332 1361 1333 printf("Purging %s (%s) 1362 printf("Purging %s (%s)...\n", package_name, package_version); 1334 1363 1335 1364 /* run prerm script */ … … 1345 1374 1346 1375 /* Some directories cant be removed straight away, so do multiple passes */ 1347 while (remove_file_array(remove_files, exclude_files)) ;1376 while (remove_file_array(remove_files, exclude_files)) /* repeat */; 1348 1377 free_array(remove_files); 1349 1378 … … 1355 1384 1356 1385 /* run postrm script */ 1357 if (run_package_script(package_name, "postrm") == -1) {1358 bb_error_msg_and_die("postrm f ialure.. set status to what?");1386 if (run_package_script(package_name, "postrm") != 0) { 1387 bb_error_msg_and_die("postrm failure.. set status to what?"); 1359 1388 } 1360 1389 … … 1370 1399 ar_handle = init_handle(); 1371 1400 ar_handle->filter = filter_accept_list_reassign; 1372 ar_handle->src_fd = bb_xopen(filename, O_RDONLY);1373 1374 return (ar_handle);1401 ar_handle->src_fd = xopen(filename, O_RDONLY); 1402 1403 return ar_handle; 1375 1404 } 1376 1405 … … 1384 1413 1385 1414 /* We don't care about data.tar.* or debian-binary, just control.tar.* */ 1386 #if def CONFIG_FEATURE_DEB_TAR_GZ1387 llist_add_to(&(ar_handle->accept), "control.tar.gz");1415 #if ENABLE_FEATURE_DEB_TAR_GZ 1416 llist_add_to(&(ar_handle->accept), (char*)"control.tar.gz"); 1388 1417 #endif 1389 #if def CONFIG_FEATURE_DEB_TAR_BZ21390 llist_add_to(&(ar_handle->accept), "control.tar.bz2");1418 #if ENABLE_FEATURE_DEB_TAR_BZ2 1419 llist_add_to(&(ar_handle->accept), (char*)"control.tar.bz2"); 1391 1420 #endif 1392 1421 1393 1422 /* Assign the tar handle as a subarchive of the ar handle */ 1394 1423 ar_handle->sub_archive = tar_handle; 1395 1396 return;1397 1424 } 1398 1425 … … 1406 1433 1407 1434 /* We don't care about control.tar.* or debian-binary, just data.tar.* */ 1408 #if def CONFIG_FEATURE_DEB_TAR_GZ1409 llist_add_to(&(ar_handle->accept), "data.tar.gz");1435 #if ENABLE_FEATURE_DEB_TAR_GZ 1436 llist_add_to(&(ar_handle->accept), (char*)"data.tar.gz"); 1410 1437 #endif 1411 #if def CONFIG_FEATURE_DEB_TAR_BZ21412 llist_add_to(&(ar_handle->accept), "data.tar.bz2");1438 #if ENABLE_FEATURE_DEB_TAR_BZ2 1439 llist_add_to(&(ar_handle->accept), (char*)"data.tar.bz2"); 1413 1440 #endif 1414 1441 1415 1442 /* Assign the tar handle as a subarchive of the ar handle */ 1416 1443 ar_handle->sub_archive = tar_handle; 1417 1418 return;1419 1444 } 1420 1445 … … 1428 1453 close(ar_handle->src_fd); 1429 1454 1430 return (ar_handle->sub_archive->buffer);1455 return ar_handle->sub_archive->buffer; 1431 1456 } 1432 1457 … … 1437 1462 name_ptr += strspn(name_ptr, "./"); 1438 1463 if (name_ptr[0] != '\0') { 1439 archive_handle->file_header->name = bb_xasprintf("%s%s", archive_handle->buffer, name_ptr);1464 archive_handle->file_header->name = xasprintf("%s%s", archive_handle->buffer, name_ptr); 1440 1465 data_extract_all(archive_handle); 1441 1466 } 1442 return;1443 1467 } 1444 1468 … … 1446 1470 { 1447 1471 const char *package_name = name_hashtable[package_hashtable[deb_file->package]->name]; 1448 const unsigned intstatus_num = search_status_hashtable(package_name);1449 const unsigned intstatus_package_num = status_hashtable[status_num]->package;1472 const unsigned status_num = search_status_hashtable(package_name); 1473 const unsigned status_package_num = status_hashtable[status_num]->package; 1450 1474 char *info_prefix; 1475 char *list_filename; 1451 1476 archive_handle_t *archive_handle; 1452 1477 FILE *out_stream; … … 1457 1482 if (strcmp(name_hashtable[get_status(status_num, 3)], "installed") == 0) { 1458 1483 /* Package is already installed, remove old version first */ 1459 printf("Preparing to replace %s %s (using %s) 1484 printf("Preparing to replace %s %s (using %s)...\n", package_name, 1460 1485 name_hashtable[package_hashtable[status_package_num]->version], 1461 1486 deb_file->filename); 1462 1487 remove_package(status_package_num, 0); 1463 1488 } else { 1464 printf("Unpacking %s (from %s) 1489 printf("Unpacking %s (from %s)...\n", package_name, deb_file->filename); 1465 1490 } 1466 1491 1467 1492 /* Extract control.tar.gz to /var/lib/dpkg/info/<package>.filename */ 1468 info_prefix = bb_xasprintf("/var/lib/dpkg/info/%s.", package_name);1493 info_prefix = xasprintf("/var/lib/dpkg/info/%s.", package_name); 1469 1494 archive_handle = init_archive_deb_ar(deb_file->filename); 1470 1495 init_archive_deb_control(archive_handle); 1471 1496 1472 while (all_control_files[i]) {1473 char *c = bb_xasprintf("./%s", all_control_files[i]);1497 while (all_control_files[i]) { 1498 char *c = xasprintf("./%s", all_control_files[i]); 1474 1499 llist_add_to(&accept_list, c); 1475 1500 i++; … … 1485 1510 if (run_package_script(package_name, "preinst") != 0) { 1486 1511 /* when preinst returns exit code != 0 then quit installation process */ 1487 bb_error_msg_and_die("subprocess pre-installation script returned error .");1512 bb_error_msg_and_die("subprocess pre-installation script returned error"); 1488 1513 } 1489 1514 … … 1492 1517 init_archive_deb_data(archive_handle); 1493 1518 archive_handle->sub_archive->action_data = data_extract_all_prefix; 1494 archive_handle->sub_archive->buffer = "/";1519 archive_handle->sub_archive->buffer = (char*)"/"; /* huh? */ 1495 1520 archive_handle->sub_archive->flags |= ARCHIVE_EXTRACT_UNCONDITIONAL; 1496 1521 unpack_ar_archive(archive_handle); 1497 1522 1498 1523 /* Create the list file */ 1499 strcat(info_prefix, "list");1500 out_stream = bb_xfopen(info_prefix, "w");1524 list_filename = xasprintf("/var/lib/dpkg/info/%s.list", package_name); 1525 out_stream = xfopen(list_filename, "w"); 1501 1526 while (archive_handle->sub_archive->passed) { 1502 1527 /* the leading . has been stripped by data_extract_all_prefix already */ … … 1512 1537 1513 1538 free(info_prefix); 1539 free(list_filename); 1514 1540 } 1515 1541 … … 1520 1546 const int status_num = search_status_hashtable(package_name); 1521 1547 1522 printf("Setting up %s (%s) 1548 printf("Setting up %s (%s)...\n", package_name, package_version); 1523 1549 1524 1550 /* Run the postinst script */ 1525 1551 if (run_package_script(package_name, "postinst") != 0) { 1526 1552 /* TODO: handle failure gracefully */ 1527 bb_error_msg_and_die("post rmfailure.. set status to what?");1553 bb_error_msg_and_die("postinst failure.. set status to what?"); 1528 1554 } 1529 1555 /* Change status to reflect success */ … … 1532 1558 } 1533 1559 1560 int dpkg_main(int argc, char **argv); 1534 1561 int dpkg_main(int argc, char **argv) 1535 1562 { 1536 1563 deb_file_t **deb_file = NULL; 1537 1564 status_node_t *status_node; 1565 char *str_f; 1538 1566 int opt; 1539 1567 int package_num; 1540 int dpkg_opt = 0;1541 1568 int deb_count = 0; 1542 1569 int state_status; 1543 1570 int status_num; 1544 1571 int i; 1545 1546 while ((opt = getopt(argc, argv, "CF:ilPru")) != -1) { 1547 switch (opt) { 1548 case 'C': // equivalent to --configure in official dpkg 1549 dpkg_opt |= dpkg_opt_configure; 1550 dpkg_opt |= dpkg_opt_package_name; 1551 break; 1552 case 'F': // equivalent to --force in official dpkg 1553 if (strcmp(optarg, "depends") == 0) { 1554 dpkg_opt |= dpkg_opt_force_ignore_depends; 1555 } 1556 break; 1557 case 'i': 1558 dpkg_opt |= dpkg_opt_install; 1559 dpkg_opt |= dpkg_opt_filename; 1560 break; 1561 case 'l': 1562 dpkg_opt |= dpkg_opt_list_installed; 1563 break; 1564 case 'P': 1565 dpkg_opt |= dpkg_opt_purge; 1566 dpkg_opt |= dpkg_opt_package_name; 1567 break; 1568 case 'r': 1569 dpkg_opt |= dpkg_opt_remove; 1570 dpkg_opt |= dpkg_opt_package_name; 1571 break; 1572 case 'u': /* Equivalent to --unpack in official dpkg */ 1573 dpkg_opt |= dpkg_opt_unpack; 1574 dpkg_opt |= dpkg_opt_filename; 1575 break; 1576 default: 1577 bb_show_usage(); 1578 } 1579 } 1580 /* check for non-otion argument if expected */ 1581 if ((dpkg_opt == 0) || ((argc == optind) && !(dpkg_opt && dpkg_opt_list_installed))) { 1572 enum { 1573 OPT_configure = 0x1, 1574 OPT_force_ignore_depends = 0x2, 1575 OPT_install = 0x4, 1576 OPT_list_installed = 0x8, 1577 OPT_purge = 0x10, 1578 OPT_remove = 0x20, 1579 OPT_unpack = 0x40, 1580 }; 1581 1582 opt = getopt32(argv, "CF:ilPru", &str_f); 1583 //if (opt & OPT_configure) ... // -C 1584 if (opt & OPT_force_ignore_depends) { // -F (--force in official dpkg) 1585 if (strcmp(str_f, "depends")) 1586 opt &= ~OPT_force_ignore_depends; 1587 } 1588 //if (opt & OPT_install) ... // -i 1589 //if (opt & OPT_list_installed) ... // -l 1590 //if (opt & OPT_purge) ... // -P 1591 //if (opt & OPT_remove) ... // -r 1592 //if (opt & OPT_unpack) ... // -u (--unpack in official dpkg) 1593 argc -= optind; 1594 argv += optind; 1595 /* check for non-option argument if expected */ 1596 if (!opt || (!argc && !(opt && OPT_list_installed))) 1582 1597 bb_show_usage(); 1583 } 1598 1599 name_hashtable = xzalloc(sizeof(name_hashtable[0]) * (NAME_HASH_PRIME + 1)); 1600 package_hashtable = xzalloc(sizeof(package_hashtable[0]) * (PACKAGE_HASH_PRIME + 1)); 1601 status_hashtable = xzalloc(sizeof(status_hashtable[0]) * (STATUS_HASH_PRIME + 1)); 1584 1602 1585 1603 /* puts("(Reading database ... xxxxx files and directories installed.)"); */ … … 1587 1605 1588 1606 /* if the list action was given print the installed packages and exit */ 1589 if ( dpkg_opt & dpkg_opt_list_installed) {1607 if (opt & OPT_list_installed) { 1590 1608 list_packages(); 1591 return (EXIT_SUCCESS);1609 return EXIT_SUCCESS; 1592 1610 } 1593 1611 1594 1612 /* Read arguments and store relevant info in structs */ 1595 while ( optind < argc) {1613 while (*argv) { 1596 1614 /* deb_count = nb_elem - 1 and we need nb_elem + 1 to allocate terminal node [NULL pointer] */ 1597 deb_file = xrealloc(deb_file, sizeof(deb_file_t *) * (deb_count + 2)); 1598 deb_file[deb_count] = (deb_file_t *) xzalloc(sizeof(deb_file_t)); 1599 if (dpkg_opt & dpkg_opt_filename) { 1615 deb_file = xrealloc(deb_file, sizeof(deb_file[0]) * (deb_count + 2)); 1616 deb_file[deb_count] = xzalloc(sizeof(deb_file[0][0])); 1617 if (opt & (OPT_install | OPT_unpack)) { 1618 /* -i/-u: require filename */ 1600 1619 archive_handle_t *archive_handle; 1601 1620 llist_t *control_list = NULL; 1602 1621 1603 1622 /* Extract the control file */ 1604 llist_add_to(&control_list, "./control");1605 archive_handle = init_archive_deb_ar(argv[ optind]);1623 llist_add_to(&control_list, (char*)"./control"); 1624 archive_handle = init_archive_deb_ar(argv[0]); 1606 1625 init_archive_deb_control(archive_handle); 1607 1626 deb_file[deb_count]->control_file = deb_extract_control_file_to_buffer(archive_handle, control_list); 1608 1627 if (deb_file[deb_count]->control_file == NULL) { 1609 bb_error_msg_and_die(" Couldnt extract control file");1610 } 1611 deb_file[deb_count]->filename = bb_xstrdup(argv[optind]);1628 bb_error_msg_and_die("cannot extract control file"); 1629 } 1630 deb_file[deb_count]->filename = xstrdup(argv[0]); 1612 1631 package_num = fill_package_struct(deb_file[deb_count]->control_file); 1613 1632 1614 1633 if (package_num == -1) { 1615 bb_error_msg(" Invalid control file in %s", argv[optind]);1616 optind++;1634 bb_error_msg("invalid control file in %s", argv[0]); 1635 argv++; 1617 1636 continue; 1618 1637 } 1619 deb_file[deb_count]->package = (unsigned int) package_num;1638 deb_file[deb_count]->package = (unsigned) package_num; 1620 1639 1621 1640 /* Add the package to the status hashtable */ 1622 if ( (dpkg_opt & dpkg_opt_unpack) || (dpkg_opt & dpkg_opt_install)) {1641 if (opt & (OPT_unpack | OPT_install)) { 1623 1642 /* Try and find a currently installed version of this package */ 1624 1643 status_num = search_status_hashtable(name_hashtable[package_hashtable[deb_file[deb_count]->package]->name]); 1625 1644 /* If no previous entry was found initialise a new entry */ 1626 if ((status_hashtable[status_num] == NULL) || 1627 (status_hashtable[status_num]->status == 0)) { 1628 status_node = (status_node_t *) xmalloc(sizeof(status_node_t)); 1645 if (status_hashtable[status_num] == NULL 1646 || status_hashtable[status_num]->status == 0 1647 ) { 1648 status_node = xmalloc(sizeof(status_node_t)); 1629 1649 status_node->package = deb_file[deb_count]->package; 1630 1650 /* reinstreq isnt changed to "ok" until the package control info … … 1637 1657 } 1638 1658 } 1639 } 1640 else if (dpkg_opt & dpkg_opt_package_name) {1659 } else if (opt & (OPT_configure | OPT_purge | OPT_remove)) { 1660 /* -C/-p/-r: require package name */ 1641 1661 deb_file[deb_count]->package = search_package_hashtable( 1642 search_name_hashtable(argv[optind]),1643 search_name_hashtable("ANY"), VER_ANY);1662 search_name_hashtable(argv[0]), 1663 search_name_hashtable("ANY"), VER_ANY); 1644 1664 if (package_hashtable[deb_file[deb_count]->package] == NULL) { 1645 bb_error_msg_and_die(" Package %s is uninstalled or unknown\n", argv[optind]);1665 bb_error_msg_and_die("package %s is uninstalled or unknown", argv[0]); 1646 1666 } 1647 1667 package_num = deb_file[deb_count]->package; … … 1650 1670 1651 1671 /* check package status is "installed" */ 1652 if (dpkg_opt & dpkg_opt_remove) { 1653 if ((strcmp(name_hashtable[state_status], "not-installed") == 0) || 1654 (strcmp(name_hashtable[state_status], "config-files") == 0)) { 1655 bb_error_msg_and_die("%s is already removed.", name_hashtable[package_hashtable[package_num]->name]); 1672 if (opt & OPT_remove) { 1673 if (strcmp(name_hashtable[state_status], "not-installed") == 0 1674 || strcmp(name_hashtable[state_status], "config-files") == 0 1675 ) { 1676 bb_error_msg_and_die("%s is already removed", name_hashtable[package_hashtable[package_num]->name]); 1656 1677 } 1657 1678 set_status(status_num, "deinstall", 1); 1658 } 1659 else if (dpkg_opt & dpkg_opt_purge) { 1679 } else if (opt & OPT_purge) { 1660 1680 /* if package status is "conf-files" then its ok */ 1661 1681 if (strcmp(name_hashtable[state_status], "not-installed") == 0) { 1662 bb_error_msg_and_die("%s is already purged .", name_hashtable[package_hashtable[package_num]->name]);1682 bb_error_msg_and_die("%s is already purged", name_hashtable[package_hashtable[package_num]->name]); 1663 1683 } 1664 1684 set_status(status_num, "purge", 1); … … 1666 1686 } 1667 1687 deb_count++; 1668 optind++; 1669 } 1688 argv++; 1689 } 1690 if (!deb_count) 1691 bb_error_msg_and_die("no package files specified"); 1670 1692 deb_file[deb_count] = NULL; 1671 1693 1672 1694 /* Check that the deb file arguments are installable */ 1673 if ( (dpkg_opt & dpkg_opt_force_ignore_depends) != dpkg_opt_force_ignore_depends) {1695 if (!(opt & OPT_force_ignore_depends)) { 1674 1696 if (!check_deps(deb_file, 0, deb_count)) { 1675 bb_error_msg_and_die(" Dependency check failed");1697 bb_error_msg_and_die("dependency check failed"); 1676 1698 } 1677 1699 } … … 1680 1702 for (i = 0; i < deb_count; i++) { 1681 1703 /* Remove or purge packages */ 1682 if ( dpkg_opt & dpkg_opt_remove) {1704 if (opt & OPT_remove) { 1683 1705 remove_package(deb_file[i]->package, 1); 1684 1706 } 1685 else if ( dpkg_opt & dpkg_opt_purge) {1707 else if (opt & OPT_purge) { 1686 1708 purge_package(deb_file[i]->package); 1687 1709 } 1688 else if ( dpkg_opt & dpkg_opt_unpack) {1710 else if (opt & OPT_unpack) { 1689 1711 unpack_package(deb_file[i]); 1690 1712 } 1691 else if ( dpkg_opt & dpkg_opt_install) {1713 else if (opt & OPT_install) { 1692 1714 unpack_package(deb_file[i]); 1693 1715 /* package is configured in second pass below */ 1694 1716 } 1695 else if ( dpkg_opt & dpkg_opt_configure) {1717 else if (opt & OPT_configure) { 1696 1718 configure_package(deb_file[i]); 1697 1719 } 1698 1720 } 1699 1721 /* configure installed packages */ 1700 if ( dpkg_opt & dpkg_opt_install) {1722 if (opt & OPT_install) { 1701 1723 for (i = 0; i < deb_count; i++) 1702 1724 configure_package(deb_file[i]); … … 1705 1727 write_status_file(deb_file); 1706 1728 1707 for (i = 0; i < deb_count; i++) {1708 f ree(deb_file[i]->control_file);1709 free(deb_file[i]->filename);1710 free(deb_file[i]);1711 }1712 1713 free(deb_file); 1714 1715 for (i = 0; i < NAME_HASH_PRIME; i++) { 1716 f ree(name_hashtable[i]);1717 }1718 1719 for (i = 0; i < PACKAGE_HASH_PRIME; i++) { 1720 if (package_hashtable[i] != NULL) {1729 if (ENABLE_FEATURE_CLEAN_UP) { 1730 for (i = 0; i < deb_count; i++) { 1731 free(deb_file[i]->control_file); 1732 free(deb_file[i]->filename); 1733 free(deb_file[i]); 1734 } 1735 1736 free(deb_file); 1737 1738 for (i = 0; i < NAME_HASH_PRIME; i++) { 1739 free(name_hashtable[i]); 1740 } 1741 1742 for (i = 0; i < PACKAGE_HASH_PRIME; i++) { 1721 1743 free_package(package_hashtable[i]); 1722 1744 } 1723 } 1724 1725 for (i = 0; i < STATUS_HASH_PRIME; i++) { 1726 free(status_hashtable[i]); 1727 } 1728 1729 return(EXIT_SUCCESS); 1730 } 1731 1745 1746 for (i = 0; i < STATUS_HASH_PRIME; i++) { 1747 free(status_hashtable[i]); 1748 } 1749 1750 free(status_hashtable); 1751 free(package_hashtable); 1752 free(name_hashtable); 1753 } 1754 1755 return EXIT_SUCCESS; 1756 }
Note:
See TracChangeset
for help on using the changeset viewer.