Changeset 1770 in MondoRescue for branches/stable/mindi-busybox/archival/dpkg.c
- Timestamp:
- Nov 6, 2007, 11:01:53 AM (18 years ago)
- File:
-
- 1 edited
-
branches/stable/mindi-busybox/archival/dpkg.c (modified) (90 diffs)
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 case 0: /* Package */568 new_node->name = search_name_hashtable(field_value);569 break;570 case 1: /* Version */571 new_node->version = search_name_hashtable(field_value);572 break;573 case 2: /* Pre-Depends */574 add_split_dependencies(new_node, field_value, EDGE_PRE_DEPENDS);575 break;576 case 3: /* Depends */577 add_split_dependencies(new_node, field_value, EDGE_DEPENDS);578 break;579 case 4: /* Replaces */580 add_split_dependencies(new_node, field_value, EDGE_REPLACES);581 break;582 case 5: /* Provides */583 add_split_dependencies(new_node, field_value, EDGE_PROVIDES);584 break;585 case 6: /* Conflicts */586 add_split_dependencies(new_node, field_value, EDGE_CONFLICTS);587 break;588 case 7: /* Suggests */589 add_split_dependencies(new_node, field_value, EDGE_SUGGESTS);590 break;591 case 8: /* Recommends */592 add_split_dependencies(new_node, field_value, EDGE_RECOMMENDS);593 break;594 case 9: /* Enhances */595 add_split_dependencies(new_node, field_value, EDGE_ENHANCES);596 break;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 (! write_flag) {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 ( root_of_alternatives && package_edge->type != root_of_alternatives->type - 1)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 if (stat_str[j] == ' ') spccnt++;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) ...\n", package_name, package_version);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) ...\n", package_name,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) ...\n", package_name, deb_file->filename);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) ...\n", package_name, package_version);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.
