Standardize on the vi editing directives being on the first line.
[oweals/busybox.git] / archival / dpkg.c
index 5f9f3a76bfc12d65ad56d5ddbeb722d79dd16943..558e3cd48ce285d86a79d8964d7aa59d0936ad12 100644 (file)
@@ -1,3 +1,4 @@
+/* vi: set sw=4 ts=4: */
 /*
  *  Mini dpkg implementation for busybox.
  *  This is not meant as a replacement for dpkg
@@ -7,19 +8,7 @@
  *
  *  Started life as a busybox implementation of udpkg
  *
- *  This program is free software; you can redistribute it and/or modify
- *  it under the terms of the GNU General Public License as published by
- *  the Free Software Foundation; either version 2 of the License, or
- *  (at your option) any later version.
- *
- *  This program is distributed in the hope that it will be useful,
- *  but WITHOUT ANY WARRANTY; without even the implied warranty of
- *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- *  GNU Library General Public License for more details.
- *
- *  You should have received a copy of the GNU General Public License
- *  along with this program; if not, write to the Free Software
- *  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ * Licensed under GPLv2 or later, see file LICENSE in this tarball for details.
  */
 
 /*
@@ -544,17 +533,19 @@ static void free_package(common_node_t *node)
                for (i = 0; i < node->num_of_edges; i++) {
                        free(node->edge[i]);
                }
-               if ( node->edge )
-                       free(node->edge);
+               free(node->edge);
                free(node);
        }
 }
 
 static unsigned int fill_package_struct(char *control_buffer)
 {
-       common_node_t *new_node = (common_node_t *) xcalloc(1, sizeof(common_node_t));
-       const char *field_names[] = { "Package", "Version", "Pre-Depends", "Depends",
-               "Replaces", "Provides", "Conflicts", "Suggests", "Recommends", "Enhances", 0};
+       static const char *const field_names[] = { "Package", "Version",
+               "Pre-Depends", "Depends","Replaces", "Provides",
+               "Conflicts", "Suggests", "Recommends", "Enhances", 0
+       };
+
+       common_node_t *new_node = (common_node_t *) xzalloc(sizeof(common_node_t));
        char *field_name;
        char *field_value;
        int field_start = 0;
@@ -675,8 +666,7 @@ static void set_status(const unsigned int status_node_num, const char *new_value
                        bb_error_msg_and_die("DEBUG ONLY: this shouldnt happen");
        }
 
-       new_status = (char *) xmalloc(want_len + flag_len + status_len + 3);
-       sprintf(new_status, "%s %s %s", name_hashtable[want], name_hashtable[flag], name_hashtable[status]);
+       new_status = bb_xasprintf("%s %s %s", name_hashtable[want], name_hashtable[flag], name_hashtable[status]);
        status_hashtable[status_node_num]->status = search_name_hashtable(new_status);
        free(new_status);
        return;
@@ -739,79 +729,6 @@ static void index_status_file(const char *filename)
        return;
 }
 
-#if 0 /* this code is no longer used */
-char *get_depends_field(common_node_t *package, const int depends_type)
-{
-       char *depends = NULL;
-       char *old_sep = (char *)xcalloc(1, 3);
-       char *new_sep = (char *)xcalloc(1, 3);
-       int line_size = 0;
-       int depends_size;
-
-       int i;
-
-       for (i = 0; i < package->num_of_edges; i++) {
-               if ((package->edge[i]->type == EDGE_OR_PRE_DEPENDS) ||
-                       (package->edge[i]->type == EDGE_OR_DEPENDS)) {
-               }
-
-               if ((package->edge[i]->type == depends_type) ||
-                       (package->edge[i]->type == depends_type + 1)) {
-                       /* Check if its the first time through */
-
-                       depends_size = 8 + strlen(name_hashtable[package->edge[i]->name])
-                               + strlen(name_hashtable[package->edge[i]->version]);
-                       line_size += depends_size;
-                       depends = (char *) xrealloc(depends, line_size + 1);
-
-                       /* Check to see if this dependency is the type we are looking for
-                        * +1 to check for 'extra' types, e.g. ored dependecies */
-                       strcpy(old_sep, new_sep);
-                       if (package->edge[i]->type == depends_type) {
-                               strcpy(new_sep, ", ");
-                       }
-                       else if (package->edge[i]->type == depends_type + 1) {
-                               strcpy(new_sep, "| ");
-                       }
-
-                       if (depends_size == line_size) {
-                               strcpy(depends, "");
-                       } else {
-                               if ((strcmp(old_sep, "| ") == 0) && (strcmp(new_sep, "| ") == 0)) {
-                                       strcat(depends, " | ");
-                               } else {
-                                       strcat(depends, ", ");
-                               }
-                       }
-
-                       strcat(depends, name_hashtable[package->edge[i]->name]);
-                       if (strcmp(name_hashtable[package->edge[i]->version], "NULL") != 0) {
-                               if (package->edge[i]->operator == VER_EQUAL) {
-                                       strcat(depends, " (= ");
-                               }
-                               else if (package->edge[i]->operator == VER_LESS) {
-                                       strcat(depends, " (<< ");
-                               }
-                               else if (package->edge[i]->operator == VER_LESS_EQUAL) {
-                                       strcat(depends, " (<= ");
-                               }
-                               else if (package->edge[i]->operator == VER_MORE) {
-                                       strcat(depends, " (>> ");
-                               }
-                               else if (package->edge[i]->operator == VER_MORE_EQUAL) {
-                                       strcat(depends, " (>= ");
-                               } else {
-                                       strcat(depends, " (");
-                               }
-                               strcat(depends, name_hashtable[package->edge[i]->version]);
-                               strcat(depends, ")");
-                       }
-               }
-       }
-       return(depends);
-}
-#endif
-
 static void write_buffer_no_status(FILE *new_status_file, const char *control_buffer)
 {
        char *name;
@@ -850,7 +767,7 @@ static void write_status_file(deb_file_t **deb_file)
                }
 
                tmp_string += 8;
-               tmp_string += strspn(tmp_string, " \n\t");
+               tmp_string += strspn(tmp_string, " \n\t");
                package_name = bb_xstrndup(tmp_string, strcspn(tmp_string, "\n\0"));
                write_flag = FALSE;
                tmp_string = strstr(control_buffer, "Status:");
@@ -958,9 +875,7 @@ static void write_status_file(deb_file_t **deb_file)
        /* Create a separate backfile to dpkg */
        if (rename("/var/lib/dpkg/status", "/var/lib/dpkg/status.udeb.bak") == -1) {
                struct stat stat_buf;
-               if (stat("/var/lib/dpkg/status", &stat_buf) == 0) {
-                       bb_error_msg_and_die("Couldnt create backup status file");
-               }
+               xstat("/var/lib/dpkg/status", &stat_buf);
                /* Its ok if renaming the status file fails because status
                 * file doesnt exist, maybe we are starting from scratch */
                bb_error_msg("No status file found, creating new one");
@@ -989,8 +904,8 @@ static int package_satisfies_dependency(int package, int depend_type)
                return 0;
 
        switch (depend_type) {
-       case EDGE_PRE_DEPENDS:  return get_status(status_num, 3) == search_name_hashtable("installed");
-       case EDGE_DEPENDS:      return get_status(status_num, 1) == search_name_hashtable("install");
+       case EDGE_PRE_DEPENDS:  return get_status(status_num, 3) == search_name_hashtable("installed");
+       case EDGE_DEPENDS:      return get_status(status_num, 1) == search_name_hashtable("install");
        }
        return 0;
 }
@@ -1025,11 +940,9 @@ static int check_deps(deb_file_t **deb_file, int deb_start, int dep_max_count)
                                        package_hashtable[package_num]->edge[j]->operator);
                                if (package_hashtable[conflicts_package_num] == NULL) {
                                        /* create a new package */
-                                       common_node_t *new_node = (common_node_t *) xmalloc(sizeof(common_node_t));
+                                       common_node_t *new_node = (common_node_t *) xzalloc(sizeof(common_node_t));
                                        new_node->name = package_hashtable[package_num]->edge[j]->name;
                                        new_node->version = package_hashtable[package_num]->edge[j]->version;
-                                       new_node->num_of_edges = 0;
-                                       new_node->edge = NULL;
                                        package_hashtable[conflicts_package_num] = new_node;
                                }
                                conflicts = xrealloc(conflicts, sizeof(int) * (conflicts_num + 1));
@@ -1078,7 +991,7 @@ static int check_deps(deb_file_t **deb_file, int deb_start, int dep_max_count)
                        }
                }
                i++;
-       }       
+       }
 
 
        /* Check dependendcies */
@@ -1109,15 +1022,6 @@ static int check_deps(deb_file_t **deb_file, int deb_start, int dep_max_count)
                        continue;
                }
 
-#if 0
-               /* This might be needed so we don't complain about
-                * things which are broken but unrelated to the
-                * packages that are currently being installed
-                */
-                if (state_status == search_name_hashtable("installed"))
-                        continue;
-#endif
-
                /* This code is tested only for EDGE_DEPENDS, since I
                 * have no suitable pre-depends available. There is no
                 * reason that it shouldn't work though :-)
@@ -1125,13 +1029,13 @@ static int check_deps(deb_file_t **deb_file, int deb_start, int dep_max_count)
                for (j = 0; j < package_node->num_of_edges; j++) {
                        const edge_t *package_edge = package_node->edge[j];
                        unsigned int package_num;
-                       
+
                        if ( package_edge->type == EDGE_OR_PRE_DEPENDS ||
-                            package_edge->type == EDGE_OR_DEPENDS ) {  /* start an EDGE_OR_ list */
+                            package_edge->type == EDGE_OR_DEPENDS ) {  /* start an EDGE_OR_ list */
                                number_of_alternatives = package_edge->version;
                                root_of_alternatives = package_edge;
                                continue;
-                       } else if ( number_of_alternatives == 0 ) {     /* not in the middle of an EDGE_OR_ list */
+                       } else if ( number_of_alternatives == 0 ) {     /* not in the middle of an EDGE_OR_ list */
                                number_of_alternatives = 1;
                                root_of_alternatives = NULL;
                        }
@@ -1277,15 +1181,10 @@ static int run_package_script(const char *package_name, const char *script_type)
        char *script_path;
        int result;
 
-       script_path = xmalloc(strlen(package_name) + strlen(script_type) + 21);
-       sprintf(script_path, "/var/lib/dpkg/info/%s.%s", package_name, script_type);
+       script_path = bb_xasprintf("/var/lib/dpkg/info/%s.%s", package_name, script_type);
 
        /* If the file doesnt exist is isnt a fatal */
-       if (lstat(script_path, &path_stat) < 0) {
-               result = EXIT_SUCCESS;
-       } else {
-               result = system(script_path);
-       }
+       result = lstat(script_path, &path_stat) < 0 ? EXIT_SUCCESS : system(script_path);
        free(script_path);
        return(result);
 }
@@ -1299,13 +1198,11 @@ static char **all_control_list(const char *package_name)
        char **remove_files;
 
        /* Create a list of all /var/lib/dpkg/info/<package> files */
-       remove_files = xmalloc(sizeof(all_control_files));
+       remove_files = xzalloc(sizeof(all_control_files));
        while (all_control_files[i]) {
-               remove_files[i] = xmalloc(strlen(package_name) + strlen(all_control_files[i]) + 21);
-               sprintf(remove_files[i], "/var/lib/dpkg/info/%s.%s", package_name, all_control_files[i]);
+               remove_files[i] = bb_xasprintf("/var/lib/dpkg/info/%s.%s", package_name, all_control_files[i]);
                i++;
        }
-       remove_files[sizeof(all_control_files)/sizeof(char*) - 1] = NULL;
 
        return(remove_files);
 }
@@ -1329,7 +1226,7 @@ static void free_array(char **array)
  */
 static void list_packages(void)
 {
-        int i;
+       int i;
 
        printf("    Name           Version\n");
        printf("+++-==============-==============\n");
@@ -1398,11 +1295,9 @@ static void remove_package(const unsigned int package_num, int noisy)
        free_array(remove_files);
 
        /* Create a list of files in /var/lib/dpkg/info/<package>.* to keep  */
-       exclude_files = xmalloc(sizeof(char*) * 3);
+       exclude_files = xzalloc(sizeof(char*) * 3);
        exclude_files[0] = bb_xstrdup(conffile_name);
-       exclude_files[1] = xmalloc(package_name_length + 27);
-       sprintf(exclude_files[1], "/var/lib/dpkg/info/%s.postrm", package_name);
-       exclude_files[2] = NULL;
+       exclude_files[1] = bb_xasprintf("/var/lib/dpkg/info/%s.postrm", package_name);
 
        /* Create a list of all /var/lib/dpkg/info/<package> files */
        remove_files = all_control_list(package_name);
@@ -1438,8 +1333,7 @@ static void purge_package(const unsigned int package_num)
        sprintf(list_name, "/var/lib/dpkg/info/%s.list", package_name);
        remove_files = create_list(list_name);
 
-       exclude_files = xmalloc(sizeof(char*));
-       exclude_files[0] = NULL;
+       exclude_files = xzalloc(sizeof(char*));
 
        /* Some directories cant be removed straight away, so do multiple passes */
        while (remove_file_array(remove_files, exclude_files));
@@ -1482,10 +1376,10 @@ static void init_archive_deb_control(archive_handle_t *ar_handle)
 
        /* We don't care about data.tar.* or debian-binary, just control.tar.* */
 #ifdef CONFIG_FEATURE_DEB_TAR_GZ
-       ar_handle->accept = llist_add_to(NULL, "control.tar.gz");
+       llist_add_to(&(ar_handle->accept), "control.tar.gz");
 #endif
 #ifdef CONFIG_FEATURE_DEB_TAR_BZ2
-       ar_handle->accept = llist_add_to(ar_handle->accept, "control.tar.bz2");
+       llist_add_to(&(ar_handle->accept), "control.tar.bz2");
 #endif
 
        /* Assign the tar handle as a subarchive of the ar handle */
@@ -1504,10 +1398,10 @@ static void init_archive_deb_data(archive_handle_t *ar_handle)
 
        /* We don't care about control.tar.* or debian-binary, just data.tar.* */
 #ifdef CONFIG_FEATURE_DEB_TAR_GZ
-       ar_handle->accept = llist_add_to(NULL, "data.tar.gz");
+       llist_add_to(&(ar_handle->accept), "data.tar.gz");
 #endif
 #ifdef CONFIG_FEATURE_DEB_TAR_BZ2
-       ar_handle->accept = llist_add_to(ar_handle->accept, "data.tar.bz2");
+       llist_add_to(&(ar_handle->accept), "data.tar.bz2");
 #endif
 
        /* Assign the tar handle as a subarchive of the ar handle */
@@ -1534,9 +1428,7 @@ static void data_extract_all_prefix(archive_handle_t *archive_handle)
 
        name_ptr += strspn(name_ptr, "./");
        if (name_ptr[0] != '\0') {
-               archive_handle->file_header->name = xmalloc(strlen(archive_handle->buffer) + 2 + strlen(name_ptr));
-               strcpy(archive_handle->file_header->name, archive_handle->buffer);
-               strcat(archive_handle->file_header->name, name_ptr);
+               archive_handle->file_header->name = bb_xasprintf("%s%s", archive_handle->buffer, name_ptr);
                data_extract_all(archive_handle);
        }
        return;
@@ -1565,15 +1457,13 @@ static void unpack_package(deb_file_t *deb_file)
        }
 
        /* Extract control.tar.gz to /var/lib/dpkg/info/<package>.filename */
-       info_prefix = (char *) xmalloc(strlen(package_name) + 20 + 4 + 2);
-       sprintf(info_prefix, "/var/lib/dpkg/info/%s.", package_name);
+       info_prefix = bb_xasprintf("/var/lib/dpkg/info/%s.", package_name);
        archive_handle = init_archive_deb_ar(deb_file->filename);
        init_archive_deb_control(archive_handle);
 
        while(all_control_files[i]) {
-               char *c = (char *) xmalloc(3 + bb_strlen(all_control_files[i]));
-               sprintf(c, "./%s", all_control_files[i]);
-               accept_list= llist_add_to(accept_list, c);
+               char *c = bb_xasprintf("./%s", all_control_files[i]);
+               llist_add_to(&accept_list, c);
                i++;
        }
        archive_handle->sub_archive->accept = accept_list;
@@ -1697,13 +1587,13 @@ int dpkg_main(int argc, char **argv)
        while (optind < argc) {
                /* deb_count = nb_elem - 1 and we need nb_elem + 1 to allocate terminal node [NULL pointer] */
                deb_file = xrealloc(deb_file, sizeof(deb_file_t *) * (deb_count + 2));
-               deb_file[deb_count] = (deb_file_t *) xmalloc(sizeof(deb_file_t));
+               deb_file[deb_count] = (deb_file_t *) xzalloc(sizeof(deb_file_t));
                if (dpkg_opt & dpkg_opt_filename) {
                        archive_handle_t *archive_handle;
                        llist_t *control_list = NULL;
 
                        /* Extract the control file */
-                       control_list = llist_add_to(NULL, "./control");
+                       llist_add_to(&control_list, "./control");
                        archive_handle = init_archive_deb_ar(argv[optind]);
                        init_archive_deb_control(archive_handle);
                        deb_file[deb_count]->control_file = deb_extract_control_file_to_buffer(archive_handle, control_list);
@@ -1715,7 +1605,7 @@ int dpkg_main(int argc, char **argv)
 
                        if (package_num == -1) {
                                bb_error_msg("Invalid control file in %s", argv[optind]);
-                                optind++;
+                               optind++;
                                continue;
                        }
                        deb_file[deb_count]->package = (unsigned int) package_num;
@@ -1740,8 +1630,6 @@ int dpkg_main(int argc, char **argv)
                        }
                }
                else if (dpkg_opt & dpkg_opt_package_name) {
-                       deb_file[deb_count]->filename = NULL;
-                       deb_file[deb_count]->control_file = NULL;
                        deb_file[deb_count]->package = search_package_hashtable(
                                search_name_hashtable(argv[optind]),
                                search_name_hashtable("ANY"), VER_ANY);