Changeset 1765 in MondoRescue for branches/2.2.5/mindi-busybox/archival/dpkg.c


Ignore:
Timestamp:
Nov 4, 2007, 3:16:40 AM (16 years ago)
Author:
Bruno Cornec
Message:

Update to busybox 1.7.2

File:
1 edited

Legend:

Unmodified
Added
Removed
  • branches/2.2.5/mindi-busybox/archival/dpkg.c

    r821 r1765  
     1/* vi: set sw=4 ts=4: */
    12/*
    2  *  Mini dpkg implementation for busybox.
    3  *  This is not meant as a replacement for dpkg
     3 *  mini dpkg implementation for busybox.
     4 *  this is not meant as a replacement for dpkg
    45 *
    5  *  Written By Glenn McGrath with the help of others
    6  *  Copyright (C) 2001 by Glenn McGrath
     6 *  written by glenn mcgrath with the help of others
     7 *  copyright (c) 2001 by glenn mcgrath
    78 *
    8  *  Started life as a busybox implementation of udpkg
     9 *  started life as a busybox implementation of udpkg
    910 *
    10  * Licensed under GPLv2 or later, see file LICENSE in this tarball for details.
     11 * licensed under gplv2 or later, see file license in this tarball for details.
    1112 */
    1213
    1314/*
    14  * Known difference between busybox dpkg and the official dpkg that i don't
     15 * known difference between busybox dpkg and the official dpkg that i don't
    1516 * consider important, its worth keeping a note of differences anyway, just to
    1617 * 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 the
    19  *      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.
    2021 *
    21  * Bugs that need to be fixed
     22 * bugs that need to be fixed
    2223 *  - (unknown, please let me know when you find any)
    2324 *
    2425 */
    2526
    26 #include <fcntl.h>
    27 #include <getopt.h>
    28 #include <stdlib.h>
    29 #include <string.h>
    30 #include <unistd.h>
     27#include "libbb.h"
    3128#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%
    3733 *    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 looking
     34 * 3) all _hash_prime's must be a prime number or chaos is assured, if your looking
    3935 *    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 its
    41  *    sometimes cast to an unsigned int, if you go to 16 bit you will overlap
     36 * 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
    4238 *    int's and chaos is assured, 16381 is the max prime for 14 bit field
    4339 */
     
    4743 * as there a lot of duplicate version numbers */
    4844#define NAME_HASH_PRIME 16381
    49 static char *name_hashtable[NAME_HASH_PRIME + 1];
    5045
    5146/* PACKAGE_HASH_PRIME, Maximum number of unique packages,
     
    5954#define PACKAGE_HASH_PRIME 10007
    6055typedef struct edge_s {
    61     unsigned int operator:3;
    62     unsigned int type: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 */
    6560} edge_t;
    6661
    6762typedef 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 */
    7166    edge_t **edge;
    7267} common_node_t;
    73 static common_node_t *package_hashtable[PACKAGE_HASH_PRIME + 1];
    7468
    7569/* Currently it doesnt store packages that have state-status of not-installed
     
    7872#define STATUS_HASH_PRIME 8191
    7973typedef 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 */
    8276} 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 */
     79static char **name_hashtable;             /* [NAME_HASH_PRIME + 1] */
     80static common_node_t **package_hashtable; /* [PACKAGE_HASH_PRIME + 1] */
     81static status_node_t **status_hashtable;  /* [STATUS_HASH_PRIME + 1] */
    8482
    8583/* Even numbers are for 'extras', like ored dependencies or null */
     
    107105};
    108106
    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 = 256
    119 };
    120 
    121107typedef struct deb_file_s {
    122108    char *control_file;
    123109    char *filename;
    124     unsigned int package:14;
     110    unsigned package:16; /* was:14 */
    125111} deb_file_t;
    126112
    127113
    128 static void make_hash(const char *key, unsigned int *start, unsigned int *decrement, const int hash_prime)
    129 {
    130     unsigned long int hash_num = key[0];
     114static void make_hash(const char *key, unsigned *start, unsigned *decrement, const int hash_prime)
     115{
     116    unsigned long hash_num = key[0];
    131117    int len = strlen(key);
    132118    int i;
     
    134120    /* Maybe i should have uses a "proper" hashing algorithm here instead
    135121     * 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++) {
    137123        /* shifts the ascii based value and adds it to previous value
    138124         * shift amount is mod 24 because long int is 32 bit and data
     
    141127        hash_num += ((key[i] + key[i-1]) << ((key[i] * i) % 24));
    142128    }
    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));
    145131}
    146132
     
    148134static int search_name_hashtable(const char *key)
    149135{
    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;
    153138
    154139    make_hash(key, &probe_address, &probe_decrement, NAME_HASH_PRIME);
    155     while(name_hashtable[probe_address] != NULL) {
     140    while (name_hashtable[probe_address] != NULL) {
    156141        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;
    167151}
    168152
     
    170154 * TODO make it consistent with search_name_hashtable
    171155 */
    172 static unsigned int search_status_hashtable(const char *key)
    173 {
    174     unsigned int probe_address = 0;
    175     unsigned int probe_decrement = 0;
     156static unsigned search_status_hashtable(const char *key)
     157{
     158    unsigned probe_address = 0;
     159    unsigned probe_decrement = 0;
    176160
    177161    make_hash(key, &probe_address, &probe_decrement, STATUS_HASH_PRIME);
    178     while(status_hashtable[probe_address] != NULL) {
     162    while (status_hashtable[probe_address] != NULL) {
    179163        if (strcmp(key, name_hashtable[package_hashtable[status_hashtable[probe_address]->package]->name]) == 0) {
    180164            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;
    189172}
    190173
     
    201184    int ver_num1;
    202185    int ver_num2;
    203     int ret;
    204186
    205187    if (version1 == NULL) {
    206         version1 = bb_xstrdup("");
     188        version1 = xstrdup("");
    207189    }
    208190    if (version2 == NULL) {
    209         version2 = bb_xstrdup("");
     191        version2 = xstrdup("");
    210192    }
    211193    upstream_len1 = strlen(version1);
     
    215197        /* Compare non-digit section */
    216198        tmp_int = strcspn(&version1[len1], "0123456789");
    217         name1_char = bb_xstrndup(&version1[len1], tmp_int);
     199        name1_char = xstrndup(&version1[len1], tmp_int);
    218200        len1 += tmp_int;
    219201        tmp_int = strcspn(&version2[len2], "0123456789");
    220         name2_char = bb_xstrndup(&version2[len2], tmp_int);
     202        name2_char = xstrndup(&version2[len2], tmp_int);
    221203        len2 += tmp_int;
    222204        tmp_int = strcmp(name1_char, name2_char);
     
    224206        free(name2_char);
    225207        if (tmp_int != 0) {
    226             ret = tmp_int;
    227             goto cleanup_version_compare_part;
     208            return tmp_int;
    228209        }
    229210
    230211        /* Compare digits */
    231212        tmp_int = strspn(&version1[len1], "0123456789");
    232         name1_char = bb_xstrndup(&version1[len1], tmp_int);
     213        name1_char = xstrndup(&version1[len1], tmp_int);
    233214        len1 += tmp_int;
    234215        tmp_int = strspn(&version2[len2], "0123456789");
    235         name2_char = bb_xstrndup(&version2[len2], tmp_int);
     216        name2_char = xstrndup(&version2[len2], tmp_int);
    236217        len2 += tmp_int;
    237218        ver_num1 = atoi(name1_char);
     
    240221        free(name2_char);
    241222        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;
    253230}
    254231
     
    257234 * if ver1 > ver2 return 1,
    258235 */
    259 static int version_compare(const unsigned int ver1, const unsigned int ver2)
     236static int version_compare(const unsigned ver1, const unsigned ver2)
    260237{
    261238    char *ch_ver1 = name_hashtable[ver1];
     
    285262    }
    286263    if (epoch1 < epoch2) {
    287         return(-1);
     264        return -1;
    288265    }
    289266    else if (epoch1 > epoch2) {
    290         return(1);
     267        return 1;
    291268    }
    292269
    293270    /* 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);
    296273
    297274    /* Chop off debian version, and store for later use */
     
    307284    }
    308285    result = version_compare_part(upstream_ver1, upstream_ver2);
     286    if (!result)
     287        /* Compare debian versions */
     288        result = version_compare_part(deb_ver1, deb_ver2);
    309289
    310290    free(upstream_ver1);
    311291    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
     295static int test_version(const unsigned version1, const unsigned version2, const unsigned operator)
    322296{
    323297    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
     316static int search_package_hashtable(const unsigned name, const unsigned version, const unsigned operator)
     317{
     318    unsigned probe_address = 0;
     319    unsigned probe_decrement = 0;
    361320
    362321    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) {
    364323        if (package_hashtable[probe_address]->name == name) {
    365324            if (operator == VER_ANY) {
    366                 return(probe_address);
     325                return probe_address;
    367326            }
    368327            if (test_version(package_hashtable[probe_address]->version, version, operator)) {
    369                 return(probe_address);
     328                return probe_address;
    370329            }
    371330        }
     
    375334        }
    376335    }
    377     return(probe_address);
     336    return probe_address;
    378337}
    379338
     
    394353 * it simple for now until it proves to be a problem.
    395354 */
    396 static int search_for_provides(int needle, int start_at) {
     355static int search_for_provides(int needle, int start_at)
     356{
    397357    int i, j;
    398358    common_node_t *p;
    399359    for (i = start_at + 1; i < PACKAGE_HASH_PRIME; i++) {
    400360        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)
    404365                return i;
    405366    }
     
    427388 * this alternative.
    428389 */
    429 static void add_split_dependencies(common_node_t *parent_node, const char *whole_line, unsigned int edge_type)
    430 {
    431     char *line = bb_xstrdup(whole_line);
     390static void add_split_dependencies(common_node_t *parent_node, const char *whole_line, unsigned edge_type)
     391{
     392    char *line = xstrdup(whole_line);
    432393    char *line2;
    433394    char *line_ptr1 = NULL;
     
    444405        /* skip leading spaces */
    445406        field += strspn(field, " ");
    446         line2 = bb_xstrdup(field);
     407        line2 = xstrdup(field);
    447408        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));
    451414            or_edge->type = edge_type + 1;
    452         } else {
    453             or_edge = NULL;
    454         }
    455 
    456         if ( or_edge ) {
    457415            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
    460417            add_edge_to_node(parent_node, or_edge);
    461418        }
    462419
    463420        do {
    464             edge = (edge_t *) xmalloc(sizeof(edge_t));
     421            edge = xmalloc(sizeof(edge_t));
    465422            edge->type = edge_type;
    466423
     
    476433            } else {
    477434                /* Skip leading ' ' or '(' */
    478                 version += strspn(field2, " ");
    479                 version += strspn(version, "(");
     435                version += strspn(version, " (");
    480436                /* Calculate length of any operator characters */
    481437                offset_ch = strspn(version, "<=>");
     
    497453                        edge->operator = VER_MORE_EQUAL;
    498454                    } else {
    499                         bb_error_msg_and_die("Illegal operator\n");
     455                        bb_error_msg_and_die("illegal operator");
    500456                    }
    501457                }
     
    514470            edge->name = search_name_hashtable(field2);
    515471
    516             if ( or_edge )
     472            if (or_edge)
    517473                or_edge->version++;
    518474
    519475            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
    521479        free(line2);
    522     } while ((field = strtok_r(NULL, ",", &line_ptr1)) != NULL);
     480        field = strtok_r(NULL, ",", &line_ptr1);
     481    } while (field != NULL);
     482
    523483    free(line);
    524 
    525     return;
    526484}
    527485
    528486static void free_package(common_node_t *node)
    529487{
    530     unsigned short i;
     488    unsigned i;
    531489    if (node) {
    532490        for (i = 0; i < node->num_of_edges; i++) {
     
    538496}
    539497
    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 */
     502static 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
     583static 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));
    548591    char *field_name;
    549592    char *field_value;
     
    554597    new_node->version = search_name_hashtable("unknown");
    555598    while (field_start < buffer_length) {
    556         unsigned short field_num;
     599        unsigned field_num;
    557600
    558601        field_start += read_package_field(&control_buffer[field_start],
     
    560603
    561604        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:
    599642        free(field_name);
    600643        free(field_value);
     
    603646    if (new_node->version == search_name_hashtable("unknown")) {
    604647        free_package(new_node);
    605         return(-1);
     648        return -1;
    606649    }
    607650    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;
    614654}
    615655
    616656/* if num = 1, it returns the want status, 2 returns flag, 3 returns status */
    617 static unsigned int get_status(const unsigned int status_node, const int num)
     657static unsigned get_status(const unsigned status_node, const int num)
    618658{
    619659    char *status_string = name_hashtable[status_hashtable[status_node]->status];
    620660    char *state_sub_string;
    621     unsigned int state_sub_num;
     661    unsigned state_sub_num;
    622662    int len;
    623663    int i;
     
    630670        status_string += strspn(status_string, " ");
    631671    }
    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);
    634674    state_sub_num = search_name_hashtable(state_sub_string);
    635675    free(state_sub_string);
    636     return(state_sub_num);
    637 }
    638 
    639 static void set_status(const unsigned int status_node_num, const char *new_value, const int position)
    640 {
    641     const unsigned int new_value_len = strlen(new_value);
    642     const unsigned int new_value_num = search_name_hashtable(new_value);
    643     unsigned int want = get_status(status_node_num, 1);
    644     unsigned int flag = get_status(status_node_num, 2);
    645     unsigned int status = get_status(status_node_num, 3);
     676    return state_sub_num;
     677}
     678
     679static 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);
    646686    int want_len = strlen(name_hashtable[want]);
    647687    int flag_len = strlen(name_hashtable[flag]);
     
    650690
    651691    switch (position) {
    652         case (1):
     692        case 1:
    653693            want = new_value_num;
    654694            want_len = new_value_len;
    655695            break;
    656         case (2):
     696        case 2:
    657697            flag = new_value_num;
    658698            flag_len = new_value_len;
    659699            break;
    660         case (3):
     700        case 3:
    661701            status = new_value_num;
    662702            status_len = new_value_len;
     
    666706    }
    667707
    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]);
    669709    status_hashtable[status_node_num]->status = search_name_hashtable(new_status);
    670710    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
     713static 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";
    678718
    679719    status_want = get_status(status_num, 1);
    680720    status_state = get_status(status_num, 3);
    681721
    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"))
    684724            return "is installed";
    685         if ( status_want == search_name_hashtable("deinstall") )
     725        if (status_want == search_name_hashtable("deinstall"))
    686726            return "is marked to be removed";
    687         if ( status_want == search_name_hashtable("purge") )
     727        if (status_want == search_name_hashtable("purge"))
    688728            return "is marked to be purged";
    689729    }
    690     if ( status_want ==  search_name_hashtable("unknown") )
     730    if (status_want == search_name_hashtable("unknown"))
    691731        return "is in an indeterminate state";
    692     if ( status_want == search_name_hashtable("install") )
     732    if (status_want == search_name_hashtable("install"))
    693733        return "is marked to be installed";
    694734
     
    703743    char *status_line;
    704744    status_node_t *status_node = NULL;
    705     unsigned int status_num;
    706 
    707     status_file = bb_xfopen(filename, "r");
    708     while ((control_buffer = fgets_str(status_file, "\n\n")) != NULL) {
    709         const unsigned int package_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);
    710750        if (package_num != -1) {
    711751            status_node = xmalloc(sizeof(status_node_t));
     
    715755                status_line += 7;
    716756                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"));
    718758                status_node->status = search_name_hashtable(status_line);
    719759                free(status_line);
     
    726766    }
    727767    fclose(status_file);
    728     return;
    729768}
    730769
     
    743782        }
    744783    }
    745     return;
    746784}
    747785
     
    749787static void write_status_file(deb_file_t **deb_file)
    750788{
    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");
    753791    char *package_name;
    754792    char *status_from_file;
     
    761799
    762800    /* 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) {
    765804            continue;
    766805        }
     
    768807        tmp_string += 8;
    769808        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"));
    771810        write_flag = FALSE;
    772811        tmp_string = strstr(control_buffer, "Status:");
     
    775814            tmp_string += 7;
    776815            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"));
    778817        } else {
    779818            status_from_file = NULL;
     
    787826                /* New status isnt exactly the same as old status */
    788827                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                ) {
    791831                    /* We need to add the control file from the package */
    792832                    i = 0;
    793                     while(deb_file[i] != NULL) {
     833                    while (deb_file[i] != NULL) {
    794834                        if (strcmp(package_name, name_hashtable[package_hashtable[deb_file[i]->package]->name]) == 0) {
    795835                            /* Write a status file entry with a modified status */
     
    797837                            write_buffer_no_status(new_status_file, deb_file[i]->control_file);
    798838                            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]);
    800841                            write_flag = TRUE;
    801842                            break;
     
    805846                    /* This is temperary, debugging only */
    806847                    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);
    808851                    }
    809852                }
     
    850893        }
    851894        /* If the package from the status file wasnt handle above, do it now*/
    852         if (! write_flag) {
     895        if (!write_flag) {
    853896            fprintf(new_status_file, "%s\n\n", control_buffer);
    854897        }
     
    860903
    861904    /* Write any new packages */
    862     for(i = 0; deb_file[i] != NULL; i++) {
     905    for (i = 0; deb_file[i] != NULL; i++) {
    863906        status_num = search_status_hashtable(name_hashtable[package_hashtable[deb_file[i]->package]->name]);
    864907        if (strcmp("reinstreq", name_hashtable[get_status(status_num, 2)]) == 0) {
     
    878921        /* Its ok if renaming the status file fails because status
    879922         * 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");
    881924    }
    882925
    883926    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");
    885929    }
    886930}
     
    900944     * provides which cannot satisfy any dependency by itself.
    901945     */
    902     if ( status_hashtable[status_num] == NULL )
     946    if (status_hashtable[status_num] == NULL)
    903947        return 0;
    904948
     
    927971     * installed package for conflicts*/
    928972    while (deb_file[i] != NULL) {
    929         const unsigned int package_num = deb_file[i]->package;
     973        const unsigned package_num = deb_file[i]->package;
    930974        conflicts = xrealloc(conflicts, sizeof(int) * (conflicts_num + 1));
    931975        conflicts[conflicts_num] = package_num;
     
    940984                if (package_hashtable[conflicts_package_num] == NULL) {
    941985                    /* 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));
    943987                    new_node->name = package_hashtable[package_num]->edge[j]->name;
    944988                    new_node->version = package_hashtable[package_num]->edge[j]->version;
     
    9691013
    9701014            if (package_edge->type == EDGE_CONFLICTS) {
    971                 const unsigned int package_num =
     1015                const unsigned package_num =
    9721016                    search_package_hashtable(package_edge->name,
    9731017                                 package_edge->version,
     
    9841028
    9851029                if (result) {
    986                     bb_error_msg_and_die("Package %s conflicts with %s",
     1030                    bb_error_msg_and_die("package %s conflicts with %s",
    9871031                        name_hashtable[package_node->name],
    9881032                        name_hashtable[package_edge->name]);
     
    10051049         * no dependencies to check.
    10061050         */
    1007         if ( package_node == NULL ) continue;
     1051        if (package_node == NULL) continue;
    10081052
    10091053        status_num = search_status_hashtable(name_hashtable[package_node->name]);
     
    10131057         * case there are no dependencies to check.
    10141058         */
    1015         if ( status_hashtable[status_num] == NULL ) continue;
     1059        if (status_hashtable[status_num] == NULL) continue;
    10161060
    10171061        /* If we don't want this package installed then we may
     
    10211065            continue;
    10221066        }
    1023 
    1024 #if 0
    1025         /* This might be needed so we don't complain about
    1026          * things which are broken but unrelated to the
    1027          * packages that are currently being installed
    1028          */
    1029         if (state_status == search_name_hashtable("installed"))
    1030             continue;
    1031 #endif
    10321067
    10331068        /* This code is tested only for EDGE_DEPENDS, since I
     
    10371072        for (j = 0; j < package_node->num_of_edges; j++) {
    10381073            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 */
    10431079                number_of_alternatives = package_edge->version;
    10441080                root_of_alternatives = package_edge;
    10451081                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 */
    10471084                number_of_alternatives = 1;
    10481085                root_of_alternatives = NULL;
     
    10521089
    10531090            if (package_edge->type == EDGE_PRE_DEPENDS ||
    1054                 package_edge->type == EDGE_DEPENDS ) {
     1091                package_edge->type == EDGE_DEPENDS) {
    10551092                int result=1;
    10561093                status_num = 0;
     
    10621099                 * EDGE_PRE_DEPENDS == OR_PRE_DEPENDS -1
    10631100                 */
    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",
    10661103                                 package_edge->type, root_of_alternatives->type);
    10671104
     
    10721109                    int provider = -1;
    10731110
    1074                     while ( (provider = search_for_provides(package_edge->name, provider) ) > -1 ) {
    1075                         if ( package_hashtable[provider] == NULL ) {
    1076                             printf("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");
    10771114                            continue;
    10781115                        }
    10791116                        result = !package_satisfies_dependency(provider, package_edge->type);
    10801117
    1081                         if ( result == 0 )
     1118                        if (result == 0)
    10821119                            break;
    10831120                    }
     
    10871124                number_of_alternatives--;
    10881125                if (result && number_of_alternatives == 0) {
    1089                     if ( root_of_alternatives )
     1126                    if (root_of_alternatives)
    10901127                        bb_error_msg_and_die(
    1091                             "Package %s %sdepends on %s, "
     1128                            "package %s %sdepends on %s, "
    10921129                            "which cannot be satisfied",
    10931130                            name_hashtable[package_node->name],
    10941131                            package_edge->type == EDGE_PRE_DEPENDS ? "pre-" : "",
    10951132                            name_hashtable[root_of_alternatives->name]);
    1096                     else
    1097                         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) {
    11041141                    /* we've found a package which
    11051142                     * satisfies the dependency,
     
    11141151    }
    11151152    free(conflicts);
    1116     return(TRUE);
     1153    return TRUE;
    11171154}
    11181155
     
    11271164    list_stream = fopen(filename, "r");
    11281165    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) {
    11331170        file_list = xrealloc(file_list, sizeof(char *) * (count + 2));
    11341171        file_list[count] = line;
     
    11381175
    11391176    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;
    11451181}
    11461182
     
    11491185{
    11501186    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;
    11541189
    11551190    if (remove_names == NULL) {
    1156         return(FALSE);
     1191        return 0;
    11571192    }
    11581193    for (i = 0; remove_names[i] != NULL; i++) {
    1159         match_flag = FALSE;
    11601194        if (exclude_names != NULL) {
    1161             for (j = 0; exclude_names[j] != 0; j++) {
     1195            for (j = 0; exclude_names[j] != NULL; j++) {
    11621196                if (strcmp(remove_names[i], exclude_names[j]) == 0) {
    1163                     match_flag = TRUE;
    1164                     break;
     1197                    goto skip;
    11651198                }
    11661199            }
    11671200        }
    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);
    11841214}
    11851215
     
    11901220    int result;
    11911221
    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);
    11931223
    11941224    /* If the file doesnt exist is isnt a fatal */
    11951225    result = lstat(script_path, &path_stat) < 0 ? EXIT_SUCCESS : system(script_path);
    11961226    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
     1230static const char *const all_control_files[] = {
     1231    "preinst", "postinst", "prerm", "postrm",
     1232    "list", "md5sums", "shlibs", "conffiles",
     1233    "config", "templates", NULL
     1234};
    12021235
    12031236static char **all_control_list(const char *package_name)
    12041237{
    1205     unsigned short i = 0;
     1238    unsigned i = 0;
    12061239    char **remove_files;
    12071240
     
    12091242    remove_files = xzalloc(sizeof(all_control_files));
    12101243    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]);
    12121245        i++;
    12131246    }
    12141247
    1215     return(remove_files);
     1248    return remove_files;
    12161249}
    12171250
    12181251static void free_array(char **array)
    12191252{
    1220 
    12211253    if (array) {
    1222         unsigned short i = 0;
     1254        unsigned i = 0;
    12231255        while (array[i]) {
    12241256            free(array[i]);
     
    12371269    int i;
    12381270
    1239     printf("    Name           Version\n");
    1240     printf("+++-==============-==============\n");
     1271    puts("    Name           Version");
     1272    puts("+++-==============-==============");
    12411273
    12421274    /* 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 */
    12471278            const char *name_str;  /* package name */
    12481279            const char *vers_str;  /* version */
     
    12591290
    12601291            /* 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++;
    12631294            }
    12641295            s2 = stat_str[j];
     
    12671298            printf("%c%c  %-14s %s\n", s1, s2, name_str, vers_str);
    12681299        }
    1269     }
    1270 }
    1271 
    1272 static void remove_package(const unsigned int package_num, int noisy)
     1300    }
     1301}
     1302
     1303static void remove_package(const unsigned package_num, int noisy)
    12731304{
    12741305    const char *package_name = name_hashtable[package_hashtable[package_num]->name];
    12751306    const char *package_version = name_hashtable[package_hashtable[package_num]->version];
    1276     const unsigned int status_num = search_status_hashtable(package_name);
     1307    const unsigned status_num = search_status_hashtable(package_name);
    12771308    const int package_name_length = strlen(package_name);
    12781309    char **remove_files;
     
    12801311    char list_name[package_name_length + 25];
    12811312    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);
    12861316
    12871317    /* 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) {
    12901319        bb_error_msg_and_die("script failed, prerm failure");
    12911320    }
     
    12981327    exclude_files = create_list(conffile_name);
    12991328
    1300     /* Some directories cant 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 */;
    13021331    free_array(exclude_files);
    13031332    free_array(remove_files);
     
    13051334    /* Create a list of files in /var/lib/dpkg/info/<package>.* to keep  */
    13061335    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);
    13091338
    13101339    /* Create a list of all /var/lib/dpkg/info/<package> files */
     
    13221351}
    13231352
    1324 static void purge_package(const unsigned int package_num)
     1353static void purge_package(const unsigned package_num)
    13251354{
    13261355    const char *package_name = name_hashtable[package_hashtable[package_num]->name];
    13271356    const char *package_version = name_hashtable[package_hashtable[package_num]->version];
    1328     const unsigned int status_num = search_status_hashtable(package_name);
     1357    const unsigned status_num = search_status_hashtable(package_name);
    13291358    char **remove_files;
    13301359    char **exclude_files;
    13311360    char list_name[strlen(package_name) + 25];
    13321361
    1333     printf("Purging %s (%s) ...\n", package_name, package_version);
     1362    printf("Purging %s (%s)...\n", package_name, package_version);
    13341363
    13351364    /* run prerm script */
     
    13451374
    13461375    /* 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 */;
    13481377    free_array(remove_files);
    13491378
     
    13551384
    13561385    /* run postrm script */
    1357     if (run_package_script(package_name, "postrm") == -1) {
    1358         bb_error_msg_and_die("postrm fialure.. 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?");
    13591388    }
    13601389
     
    13701399    ar_handle = init_handle();
    13711400    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;
    13751404}
    13761405
     
    13841413
    13851414    /* We don't care about data.tar.* or debian-binary, just control.tar.* */
    1386 #ifdef CONFIG_FEATURE_DEB_TAR_GZ
    1387     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");
    13881417#endif
    1389 #ifdef CONFIG_FEATURE_DEB_TAR_BZ2
    1390     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");
    13911420#endif
    13921421
    13931422    /* Assign the tar handle as a subarchive of the ar handle */
    13941423    ar_handle->sub_archive = tar_handle;
    1395 
    1396     return;
    13971424}
    13981425
     
    14061433
    14071434    /* We don't care about control.tar.* or debian-binary, just data.tar.* */
    1408 #ifdef CONFIG_FEATURE_DEB_TAR_GZ
    1409     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");
    14101437#endif
    1411 #ifdef CONFIG_FEATURE_DEB_TAR_BZ2
    1412     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");
    14131440#endif
    14141441
    14151442    /* Assign the tar handle as a subarchive of the ar handle */
    14161443    ar_handle->sub_archive = tar_handle;
    1417 
    1418     return;
    14191444}
    14201445
     
    14281453    close(ar_handle->src_fd);
    14291454
    1430     return(ar_handle->sub_archive->buffer);
     1455    return ar_handle->sub_archive->buffer;
    14311456}
    14321457
     
    14371462    name_ptr += strspn(name_ptr, "./");
    14381463    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);
    14401465        data_extract_all(archive_handle);
    14411466    }
    1442     return;
    14431467}
    14441468
     
    14461470{
    14471471    const char *package_name = name_hashtable[package_hashtable[deb_file->package]->name];
    1448     const unsigned int status_num = search_status_hashtable(package_name);
    1449     const unsigned int status_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;
    14501474    char *info_prefix;
     1475    char *list_filename;
    14511476    archive_handle_t *archive_handle;
    14521477    FILE *out_stream;
     
    14571482    if (strcmp(name_hashtable[get_status(status_num, 3)], "installed") == 0) {
    14581483        /* 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,
    14601485            name_hashtable[package_hashtable[status_package_num]->version],
    14611486            deb_file->filename);
    14621487        remove_package(status_package_num, 0);
    14631488    } 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);
    14651490    }
    14661491
    14671492    /* 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);
    14691494    archive_handle = init_archive_deb_ar(deb_file->filename);
    14701495    init_archive_deb_control(archive_handle);
    14711496
    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]);
    14741499        llist_add_to(&accept_list, c);
    14751500        i++;
     
    14851510    if (run_package_script(package_name, "preinst") != 0) {
    14861511        /* 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");
    14881513    }
    14891514
     
    14921517    init_archive_deb_data(archive_handle);
    14931518    archive_handle->sub_archive->action_data = data_extract_all_prefix;
    1494     archive_handle->sub_archive->buffer = "/";
     1519    archive_handle->sub_archive->buffer = (char*)"/"; /* huh? */
    14951520    archive_handle->sub_archive->flags |= ARCHIVE_EXTRACT_UNCONDITIONAL;
    14961521    unpack_ar_archive(archive_handle);
    14971522
    14981523    /* 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");
    15011526    while (archive_handle->sub_archive->passed) {
    15021527        /* the leading . has been stripped by data_extract_all_prefix already */
     
    15121537
    15131538    free(info_prefix);
     1539    free(list_filename);
    15141540}
    15151541
     
    15201546    const int status_num = search_status_hashtable(package_name);
    15211547
    1522     printf("Setting up %s (%s) ...\n", package_name, package_version);
     1548    printf("Setting up %s (%s)...\n", package_name, package_version);
    15231549
    15241550    /* Run the postinst script */
    15251551    if (run_package_script(package_name, "postinst") != 0) {
    15261552        /* TODO: handle failure gracefully */
    1527         bb_error_msg_and_die("postrm failure.. set status to what?");
     1553        bb_error_msg_and_die("postinst failure.. set status to what?");
    15281554    }
    15291555    /* Change status to reflect success */
     
    15321558}
    15331559
     1560int dpkg_main(int argc, char **argv);
    15341561int dpkg_main(int argc, char **argv)
    15351562{
    15361563    deb_file_t **deb_file = NULL;
    15371564    status_node_t *status_node;
     1565    char *str_f;
    15381566    int opt;
    15391567    int package_num;
    1540     int dpkg_opt = 0;
    15411568    int deb_count = 0;
    15421569    int state_status;
    15431570    int status_num;
    15441571    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)))
    15821597        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));
    15841602
    15851603/*  puts("(Reading database ... xxxxx files and directories installed.)"); */
     
    15871605
    15881606    /* 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) {
    15901608        list_packages();
    1591         return(EXIT_SUCCESS);
     1609        return EXIT_SUCCESS;
    15921610    }
    15931611
    15941612    /* Read arguments and store relevant info in structs */
    1595     while (optind < argc) {
     1613    while (*argv) {
    15961614        /* 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 */
    16001619            archive_handle_t *archive_handle;
    16011620            llist_t *control_list = NULL;
    16021621
    16031622            /* 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]);
    16061625            init_archive_deb_control(archive_handle);
    16071626            deb_file[deb_count]->control_file = deb_extract_control_file_to_buffer(archive_handle, control_list);
    16081627            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]);
    16121631            package_num = fill_package_struct(deb_file[deb_count]->control_file);
    16131632
    16141633            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++;
    16171636                continue;
    16181637            }
    1619             deb_file[deb_count]->package = (unsigned int) package_num;
     1638            deb_file[deb_count]->package = (unsigned) package_num;
    16201639
    16211640            /* 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)) {
    16231642                /* Try and find a currently installed version of this package */
    16241643                status_num = search_status_hashtable(name_hashtable[package_hashtable[deb_file[deb_count]->package]->name]);
    16251644                /* 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));
    16291649                    status_node->package = deb_file[deb_count]->package;
    16301650                    /* reinstreq isnt changed to "ok" until the package control info
     
    16371657                }
    16381658            }
    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 */
    16411661            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);
    16441664            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]);
    16461666            }
    16471667            package_num = deb_file[deb_count]->package;
     
    16501670
    16511671            /* 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]);
    16561677                }
    16571678                set_status(status_num, "deinstall", 1);
    1658             }
    1659             else if (dpkg_opt & dpkg_opt_purge) {
     1679            } else if (opt & OPT_purge) {
    16601680                /* if package status is "conf-files" then its ok */
    16611681                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]);
    16631683                }
    16641684                set_status(status_num, "purge", 1);
     
    16661686        }
    16671687        deb_count++;
    1668         optind++;
    1669     }
     1688        argv++;
     1689    }
     1690    if (!deb_count)
     1691        bb_error_msg_and_die("no package files specified");
    16701692    deb_file[deb_count] = NULL;
    16711693
    16721694    /* 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)) {
    16741696        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");
    16761698        }
    16771699    }
     
    16801702    for (i = 0; i < deb_count; i++) {
    16811703        /* Remove or purge packages */
    1682         if (dpkg_opt & dpkg_opt_remove) {
     1704        if (opt & OPT_remove) {
    16831705            remove_package(deb_file[i]->package, 1);
    16841706        }
    1685         else if (dpkg_opt & dpkg_opt_purge) {
     1707        else if (opt & OPT_purge) {
    16861708            purge_package(deb_file[i]->package);
    16871709        }
    1688         else if (dpkg_opt & dpkg_opt_unpack) {
     1710        else if (opt & OPT_unpack) {
    16891711            unpack_package(deb_file[i]);
    16901712        }
    1691         else if (dpkg_opt & dpkg_opt_install) {
     1713        else if (opt & OPT_install) {
    16921714            unpack_package(deb_file[i]);
    16931715            /* package is configured in second pass below */
    16941716        }
    1695         else if (dpkg_opt & dpkg_opt_configure) {
     1717        else if (opt & OPT_configure) {
    16961718            configure_package(deb_file[i]);
    16971719        }
    16981720    }
    16991721    /* configure installed packages */
    1700     if (dpkg_opt & dpkg_opt_install) {
     1722    if (opt & OPT_install) {
    17011723        for (i = 0; i < deb_count; i++)
    17021724            configure_package(deb_file[i]);
     
    17051727    write_status_file(deb_file);
    17061728
    1707     for (i = 0; i < deb_count; i++) {
    1708         free(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         free(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++) {
    17211743            free_package(package_hashtable[i]);
    17221744        }
    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.