summaryrefslogtreecommitdiff
path: root/archival/dpkg.c
diff options
context:
space:
mode:
Diffstat (limited to 'archival/dpkg.c')
-rw-r--r--archival/dpkg.c184
1 files changed, 133 insertions, 51 deletions
diff --git a/archival/dpkg.c b/archival/dpkg.c
index 558e3cd..0e57720 100644
--- a/archival/dpkg.c
+++ b/archival/dpkg.c
@@ -1,44 +1,39 @@
/* vi: set sw=4 ts=4: */
/*
- * Mini dpkg implementation for busybox.
- * This is not meant as a replacement for dpkg
+ * mini dpkg implementation for busybox.
+ * this is not meant as a replacement for dpkg
*
- * Written By Glenn McGrath with the help of others
- * Copyright (C) 2001 by Glenn McGrath
+ * written by glenn mcgrath with the help of others
+ * copyright (c) 2001 by glenn mcgrath
*
- * Started life as a busybox implementation of udpkg
+ * started life as a busybox implementation of udpkg
*
- * Licensed under GPLv2 or later, see file LICENSE in this tarball for details.
+ * licensed under gplv2 or later, see file license in this tarball for details.
*/
/*
- * Known difference between busybox dpkg and the official dpkg that i don't
+ * known difference between busybox dpkg and the official dpkg that i don't
* consider important, its worth keeping a note of differences anyway, just to
* make it easier to maintain.
- * - The first value for the Confflile: field isnt placed on a new line.
- * - When installing a package the Status: field is placed at the end of the
- * section, rather than just after the Package: field.
+ * - the first value for the confflile: field isnt placed on a new line.
+ * - when installing a package the status: field is placed at the end of the
+ * section, rather than just after the package: field.
*
- * Bugs that need to be fixed
+ * bugs that need to be fixed
* - (unknown, please let me know when you find any)
*
*/
-#include <fcntl.h>
-#include <getopt.h>
-#include <stdlib.h>
-#include <string.h>
-#include <unistd.h>
-#include "unarchive.h"
#include "busybox.h"
+#include "unarchive.h"
-/* NOTE: If you vary HASH_PRIME sizes be aware,
- * 1) Tweaking these will have a big effect on how much memory this program uses.
- * 2) For computational efficiency these hash tables should be at least 20%
+/* note: if you vary hash_prime sizes be aware,
+ * 1) tweaking these will have a big effect on how much memory this program uses.
+ * 2) for computational efficiency these hash tables should be at least 20%
* larger than the maximum number of elements stored in it.
- * 3) All _HASH_PRIME's must be a prime number or chaos is assured, if your looking
+ * 3) all _hash_prime's must be a prime number or chaos is assured, if your looking
* for a prime, try http://www.utm.edu/research/primes/lists/small/10000.txt
- * 4) If you go bigger than 15 bits you may get into trouble (untested) as its
+ * 4) if you go bigger than 15 bits you may get into trouble (untested) as its
* sometimes cast to an unsigned int, if you go to 16 bit you will overlap
* int's and chaos is assured, 16381 is the max prime for 14 bit field
*/
@@ -163,7 +158,7 @@ static int search_name_hashtable(const char *key)
}
}
}
- name_hashtable[probe_address] = bb_xstrdup(key);
+ name_hashtable[probe_address] = xstrdup(key);
return(probe_address);
}
@@ -204,10 +199,10 @@ static int version_compare_part(const char *version1, const char *version2)
int ret;
if (version1 == NULL) {
- version1 = bb_xstrdup("");
+ version1 = xstrdup("");
}
if (version2 == NULL) {
- version2 = bb_xstrdup("");
+ version2 = xstrdup("");
}
upstream_len1 = strlen(version1);
upstream_len2 = strlen(version2);
@@ -215,10 +210,10 @@ static int version_compare_part(const char *version1, const char *version2)
while ((len1 < upstream_len1) || (len2 < upstream_len2)) {
/* Compare non-digit section */
tmp_int = strcspn(&version1[len1], "0123456789");
- name1_char = bb_xstrndup(&version1[len1], tmp_int);
+ name1_char = xstrndup(&version1[len1], tmp_int);
len1 += tmp_int;
tmp_int = strcspn(&version2[len2], "0123456789");
- name2_char = bb_xstrndup(&version2[len2], tmp_int);
+ name2_char = xstrndup(&version2[len2], tmp_int);
len2 += tmp_int;
tmp_int = strcmp(name1_char, name2_char);
free(name1_char);
@@ -230,10 +225,10 @@ static int version_compare_part(const char *version1, const char *version2)
/* Compare digits */
tmp_int = strspn(&version1[len1], "0123456789");
- name1_char = bb_xstrndup(&version1[len1], tmp_int);
+ name1_char = xstrndup(&version1[len1], tmp_int);
len1 += tmp_int;
tmp_int = strspn(&version2[len2], "0123456789");
- name2_char = bb_xstrndup(&version2[len2], tmp_int);
+ name2_char = xstrndup(&version2[len2], tmp_int);
len2 += tmp_int;
ver_num1 = atoi(name1_char);
ver_num2 = atoi(name2_char);
@@ -292,8 +287,8 @@ static int version_compare(const unsigned int ver1, const unsigned int ver2)
}
/* Compare upstream version */
- upstream_ver1 = bb_xstrdup(ver1_ptr);
- upstream_ver2 = bb_xstrdup(ver2_ptr);
+ upstream_ver1 = xstrdup(ver1_ptr);
+ upstream_ver2 = xstrdup(ver2_ptr);
/* Chop off debian version, and store for later use */
deb_ver1 = strrchr(upstream_ver1, '-');
@@ -429,7 +424,7 @@ static void add_edge_to_node(common_node_t *node, edge_t *edge)
*/
static void add_split_dependencies(common_node_t *parent_node, const char *whole_line, unsigned int edge_type)
{
- char *line = bb_xstrdup(whole_line);
+ char *line = xstrdup(whole_line);
char *line2;
char *line_ptr1 = NULL;
char *line_ptr2 = NULL;
@@ -444,7 +439,7 @@ static void add_split_dependencies(common_node_t *parent_node, const char *whole
do {
/* skip leading spaces */
field += strspn(field, " ");
- line2 = bb_xstrdup(field);
+ line2 = xstrdup(field);
field2 = strtok_r(line2, "|", &line_ptr2);
if ( (edge_type == EDGE_DEPENDS || edge_type == EDGE_PRE_DEPENDS) &&
(strcmp(field, field2) != 0)) {
@@ -538,6 +533,93 @@ static void free_package(common_node_t *node)
}
}
+/*
+ * Gets the next package field from package_buffer, seperated into the field name
+ * and field value, it returns the int offset to the first character of the next field
+ */
+static int read_package_field(const char *package_buffer, char **field_name, char **field_value)
+{
+ int offset_name_start = 0;
+ int offset_name_end = 0;
+ int offset_value_start = 0;
+ int offset_value_end = 0;
+ int offset = 0;
+ int next_offset;
+ int name_length;
+ int value_length;
+ int exit_flag = FALSE;
+
+ if (package_buffer == NULL) {
+ *field_name = NULL;
+ *field_value = NULL;
+ return(-1);
+ }
+ while (1) {
+ next_offset = offset + 1;
+ switch (package_buffer[offset]) {
+ case('\0'):
+ exit_flag = TRUE;
+ break;
+ case(':'):
+ if (offset_name_end == 0) {
+ offset_name_end = offset;
+ offset_value_start = next_offset;
+ }
+ /* TODO: Name might still have trailing spaces if ':' isnt
+ * immediately after name */
+ break;
+ case('\n'):
+ /* TODO: The char next_offset may be out of bounds */
+ if (package_buffer[next_offset] != ' ') {
+ exit_flag = TRUE;
+ break;
+ }
+ case('\t'):
+ case(' '):
+ /* increment the value start point if its a just filler */
+ if (offset_name_start == offset) {
+ offset_name_start++;
+ }
+ if (offset_value_start == offset) {
+ offset_value_start++;
+ }
+ break;
+ }
+ if (exit_flag) {
+ /* Check that the names are valid */
+ offset_value_end = offset;
+ name_length = offset_name_end - offset_name_start;
+ value_length = offset_value_end - offset_value_start;
+ if (name_length == 0) {
+ break;
+ }
+ if ((name_length > 0) && (value_length > 0)) {
+ break;
+ }
+
+ /* If not valid, start fresh with next field */
+ exit_flag = FALSE;
+ offset_name_start = offset + 1;
+ offset_name_end = 0;
+ offset_value_start = offset + 1;
+ offset_value_end = offset + 1;
+ offset++;
+ }
+ offset++;
+ }
+ if (name_length == 0) {
+ *field_name = NULL;
+ } else {
+ *field_name = xstrndup(&package_buffer[offset_name_start], name_length);
+ }
+ if (value_length > 0) {
+ *field_value = xstrndup(&package_buffer[offset_value_start], value_length);
+ } else {
+ *field_value = NULL;
+ }
+ return(next_offset);
+}
+
static unsigned int fill_package_struct(char *control_buffer)
{
static const char *const field_names[] = { "Package", "Version",
@@ -631,7 +713,7 @@ static unsigned int get_status(const unsigned int status_node, const int num)
status_string += strspn(status_string, " ");
}
len = strcspn(status_string, " \n\0");
- state_sub_string = bb_xstrndup(status_string, len);
+ state_sub_string = xstrndup(status_string, len);
state_sub_num = search_name_hashtable(state_sub_string);
free(state_sub_string);
return(state_sub_num);
@@ -666,7 +748,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 = bb_xasprintf("%s %s %s", name_hashtable[want], name_hashtable[flag], name_hashtable[status]);
+ new_status = 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;
@@ -705,7 +787,7 @@ static void index_status_file(const char *filename)
status_node_t *status_node = NULL;
unsigned int status_num;
- status_file = bb_xfopen(filename, "r");
+ status_file = xfopen(filename, "r");
while ((control_buffer = fgets_str(status_file, "\n\n")) != NULL) {
const unsigned int package_num = fill_package_struct(control_buffer);
if (package_num != -1) {
@@ -715,7 +797,7 @@ static void index_status_file(const char *filename)
if (status_line != NULL) {
status_line += 7;
status_line += strspn(status_line, " \n\t");
- status_line = bb_xstrndup(status_line, strcspn(status_line, "\n\0"));
+ status_line = xstrndup(status_line, strcspn(status_line, "\n\0"));
status_node->status = search_name_hashtable(status_line);
free(status_line);
}
@@ -749,8 +831,8 @@ static void write_buffer_no_status(FILE *new_status_file, const char *control_bu
/* This could do with a cleanup */
static void write_status_file(deb_file_t **deb_file)
{
- FILE *old_status_file = bb_xfopen("/var/lib/dpkg/status", "r");
- FILE *new_status_file = bb_xfopen("/var/lib/dpkg/status.udeb", "w");
+ FILE *old_status_file = xfopen("/var/lib/dpkg/status", "r");
+ FILE *new_status_file = xfopen("/var/lib/dpkg/status.udeb", "w");
char *package_name;
char *status_from_file;
char *control_buffer = NULL;
@@ -768,14 +850,14 @@ static void write_status_file(deb_file_t **deb_file)
tmp_string += 8;
tmp_string += strspn(tmp_string, " \n\t");
- package_name = bb_xstrndup(tmp_string, strcspn(tmp_string, "\n\0"));
+ package_name = xstrndup(tmp_string, strcspn(tmp_string, "\n\0"));
write_flag = FALSE;
tmp_string = strstr(control_buffer, "Status:");
if (tmp_string != NULL) {
/* Seperate the status value from the control buffer */
tmp_string += 7;
tmp_string += strspn(tmp_string, " \n\t");
- status_from_file = bb_xstrndup(tmp_string, strcspn(tmp_string, "\n"));
+ status_from_file = xstrndup(tmp_string, strcspn(tmp_string, "\n"));
} else {
status_from_file = NULL;
}
@@ -1181,7 +1263,7 @@ static int run_package_script(const char *package_name, const char *script_type)
char *script_path;
int result;
- script_path = bb_xasprintf("/var/lib/dpkg/info/%s.%s", package_name, script_type);
+ script_path = xasprintf("/var/lib/dpkg/info/%s.%s", package_name, script_type);
/* If the file doesnt exist is isnt a fatal */
result = lstat(script_path, &path_stat) < 0 ? EXIT_SUCCESS : system(script_path);
@@ -1200,7 +1282,7 @@ static char **all_control_list(const char *package_name)
/* Create a list of all /var/lib/dpkg/info/<package> files */
remove_files = xzalloc(sizeof(all_control_files));
while (all_control_files[i]) {
- remove_files[i] = bb_xasprintf("/var/lib/dpkg/info/%s.%s", package_name, all_control_files[i]);
+ remove_files[i] = xasprintf("/var/lib/dpkg/info/%s.%s", package_name, all_control_files[i]);
i++;
}
@@ -1296,8 +1378,8 @@ static void remove_package(const unsigned int package_num, int noisy)
/* Create a list of files in /var/lib/dpkg/info/<package>.* to keep */
exclude_files = xzalloc(sizeof(char*) * 3);
- exclude_files[0] = bb_xstrdup(conffile_name);
- exclude_files[1] = bb_xasprintf("/var/lib/dpkg/info/%s.postrm", package_name);
+ exclude_files[0] = xstrdup(conffile_name);
+ exclude_files[1] = 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);
@@ -1361,7 +1443,7 @@ static archive_handle_t *init_archive_deb_ar(const char *filename)
/* Setup an ar archive handle that refers to the gzip sub archive */
ar_handle = init_handle();
ar_handle->filter = filter_accept_list_reassign;
- ar_handle->src_fd = bb_xopen(filename, O_RDONLY);
+ ar_handle->src_fd = xopen(filename, O_RDONLY);
return(ar_handle);
}
@@ -1428,7 +1510,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 = bb_xasprintf("%s%s", archive_handle->buffer, name_ptr);
+ archive_handle->file_header->name = xasprintf("%s%s", archive_handle->buffer, name_ptr);
data_extract_all(archive_handle);
}
return;
@@ -1457,12 +1539,12 @@ static void unpack_package(deb_file_t *deb_file)
}
/* Extract control.tar.gz to /var/lib/dpkg/info/<package>.filename */
- info_prefix = bb_xasprintf("/var/lib/dpkg/info/%s.", package_name);
+ info_prefix = 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 = bb_xasprintf("./%s", all_control_files[i]);
+ char *c = xasprintf("./%s", all_control_files[i]);
llist_add_to(&accept_list, c);
i++;
}
@@ -1489,7 +1571,7 @@ static void unpack_package(deb_file_t *deb_file)
/* Create the list file */
strcat(info_prefix, "list");
- out_stream = bb_xfopen(info_prefix, "w");
+ out_stream = xfopen(info_prefix, "w");
while (archive_handle->sub_archive->passed) {
/* the leading . has been stripped by data_extract_all_prefix already */
fputs(archive_handle->sub_archive->passed->data, out_stream);
@@ -1600,7 +1682,7 @@ int dpkg_main(int argc, char **argv)
if (deb_file[deb_count]->control_file == NULL) {
bb_error_msg_and_die("Couldnt extract control file");
}
- deb_file[deb_count]->filename = bb_xstrdup(argv[optind]);
+ deb_file[deb_count]->filename = xstrdup(argv[optind]);
package_num = fill_package_struct(deb_file[deb_count]->control_file);
if (package_num == -1) {