2001-07-14 00:05:24 +05:30
|
|
|
/*
|
|
|
|
* Mini dpkg implementation for busybox.
|
|
|
|
* This is not meant as a replacemnt for dpkg
|
|
|
|
*
|
2001-10-03 08:40:35 +05:30
|
|
|
* Written By Glenn McGrath with the help of others
|
2001-07-14 00:05:24 +05:30
|
|
|
* Copyright (C) 2001 by Glenn McGrath
|
|
|
|
*
|
|
|
|
* 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.
|
|
|
|
*/
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Known difference between busybox dpkg and the official dpkg that i dont
|
|
|
|
* 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.
|
|
|
|
* - The <package>.control file is extracted and kept in the info dir.
|
|
|
|
* - When installing a package the Status: field is placed at the end of the
|
|
|
|
* section, rather than just after the Package: field.
|
|
|
|
* - Packages with previously unknown status are inserted at the begining of
|
|
|
|
* the status file
|
|
|
|
*
|
2001-10-25 19:56:05 +05:30
|
|
|
* Work to be done
|
|
|
|
* - (bugs, unknown, please let me know when you find them)
|
|
|
|
* - dependency checking is incomplete
|
|
|
|
* - provides, replaces, conflicts fields arent considered when installing
|
2001-07-14 00:05:24 +05:30
|
|
|
*/
|
|
|
|
|
2001-04-08 10:57:18 +05:30
|
|
|
#include <getopt.h>
|
2001-02-10 07:35:24 +05:30
|
|
|
#include <stdlib.h>
|
2001-07-14 00:05:24 +05:30
|
|
|
#include <string.h>
|
2001-02-10 07:35:24 +05:30
|
|
|
#include <unistd.h>
|
2001-10-25 19:56:05 +05:30
|
|
|
#include "../libbb/deb_functs.h"
|
|
|
|
#include "libbb.h"
|
2001-02-10 07:35:24 +05:30
|
|
|
#include "busybox.h"
|
|
|
|
|
2001-07-14 00:05:24 +05:30
|
|
|
enum dpkg_opt_e {
|
2001-10-25 19:56:05 +05:30
|
|
|
DPKG_OPT_PURGE = 1,
|
|
|
|
DPKG_OPT_REMOVE = 2,
|
|
|
|
DPKG_OPT_UNPACK = 4,
|
|
|
|
DPKG_OPT_CONFIGURE = 8,
|
|
|
|
DPKG_OPT_INSTALL = 16,
|
|
|
|
DPKG_OPT_PACKAGENAME = 32,
|
|
|
|
DPKG_OPT_FILENAME = 64,
|
|
|
|
DPKG_OPT_LIST_INSTALLED = 128,
|
|
|
|
DPKG_OPT_FORCE_IGNORE_DEPENDS = 256,
|
2001-07-14 00:05:24 +05:30
|
|
|
};
|
2001-10-25 19:56:05 +05:30
|
|
|
extern unsigned short char_name_hash_prime;
|
|
|
|
extern unsigned short char_ver_hash_prime;
|
|
|
|
extern unsigned short char_rev_hash_prime;
|
|
|
|
extern unsigned short char_filename_hash_prime;
|
|
|
|
extern unsigned short char_source_hash_prime;
|
|
|
|
extern unsigned short edge_hash_prime;
|
|
|
|
extern unsigned short node_hash_prime;
|
2001-07-14 00:05:24 +05:30
|
|
|
|
2001-10-25 19:56:05 +05:30
|
|
|
/* This function lists information on the installed packages. It loops through
|
|
|
|
* the status_hashtable to retrieve the info. This results in smaller code than
|
|
|
|
* scanning the status file. The resulting list, however, is unsorted.
|
2001-02-10 07:35:24 +05:30
|
|
|
*/
|
2001-10-25 19:56:05 +05:30
|
|
|
/* TODO: check the character flags ive assigned match real dpkg */
|
|
|
|
#ifdef BB_FEATURE_DPKG_LIST
|
|
|
|
extern void list_packages(void)
|
2001-02-10 07:35:24 +05:30
|
|
|
{
|
2001-10-25 19:56:05 +05:30
|
|
|
int i;
|
2001-07-14 00:05:24 +05:30
|
|
|
|
2001-10-25 19:56:05 +05:30
|
|
|
printf(" Name Version\n");
|
|
|
|
printf("+++-==============-==============\n");
|
2001-07-14 00:05:24 +05:30
|
|
|
|
2001-10-25 19:56:05 +05:30
|
|
|
/* go through status hash, dereference package hash and finally strings */
|
|
|
|
for (i = 0; i < node_hash_prime; i++) {
|
|
|
|
node_t *node = get_node_ht(i);
|
2001-07-14 00:05:24 +05:30
|
|
|
if (node != NULL) {
|
2001-10-25 19:56:05 +05:30
|
|
|
char *name_str = get_name_ht(node->name);
|
|
|
|
char *ver_rev;
|
|
|
|
char want_flag;
|
|
|
|
char status_flag;
|
2001-02-10 07:35:24 +05:30
|
|
|
|
2001-10-25 19:56:05 +05:30
|
|
|
ver_rev = version_revision(node->version, node->revision);
|
|
|
|
if (strlen(ver_rev) > 14) {
|
|
|
|
ver_rev[14] = '\0';
|
2001-07-14 00:05:24 +05:30
|
|
|
}
|
|
|
|
|
2001-10-25 19:56:05 +05:30
|
|
|
switch (node->state_want) {
|
|
|
|
case(STATE_WANT_HOLD):
|
|
|
|
want_flag = 'h';
|
2001-07-14 00:05:24 +05:30
|
|
|
break;
|
2001-10-25 19:56:05 +05:30
|
|
|
case(STATE_WANT_INSTALL):
|
|
|
|
want_flag = 'i';
|
2001-07-14 00:05:24 +05:30
|
|
|
break;
|
2001-10-25 19:56:05 +05:30
|
|
|
case(STATE_WANT_DEINSTALL):
|
|
|
|
want_flag = 'r';
|
2001-07-14 00:05:24 +05:30
|
|
|
break;
|
2001-10-25 19:56:05 +05:30
|
|
|
case(STATE_WANT_PURGE):
|
|
|
|
want_flag = 'p';
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
want_flag = '?';
|
2001-07-14 00:05:24 +05:30
|
|
|
}
|
2001-10-25 19:56:05 +05:30
|
|
|
switch(node->state_status) {
|
|
|
|
case(STATE_STATUS_NOTINSTALLED):
|
|
|
|
status_flag = 'n';
|
|
|
|
break;
|
|
|
|
case(STATE_STATUS_UNPACKED):
|
|
|
|
status_flag = 'u';
|
|
|
|
break;
|
|
|
|
case(STATE_STATUS_HALFCONFIGURED):
|
|
|
|
status_flag = 'h';
|
|
|
|
break;
|
|
|
|
case(STATE_STATUS_INSTALLED):
|
|
|
|
status_flag = 'i';
|
|
|
|
break;
|
|
|
|
case(STATE_STATUS_HALFINSTALLED):
|
|
|
|
status_flag = 'h';
|
|
|
|
break;
|
|
|
|
case(STATE_STATUS_CONFIGFILES):
|
|
|
|
status_flag = 'c';
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
status_flag = '?';
|
2001-07-14 00:05:24 +05:30
|
|
|
}
|
2001-02-12 17:03:09 +05:30
|
|
|
|
2001-09-21 10:00:51 +05:30
|
|
|
/* print out the line formatted like Debian dpkg */
|
2001-10-25 19:56:05 +05:30
|
|
|
if ((status_flag != '?') && (want_flag != '?')) {
|
|
|
|
#ifdef BB_FEATURE_DPKG_LIST_SHORT_DESCRIPTIONS
|
|
|
|
printf("%c%c %-14s %-14s %s\n", want_flag, status_flag, name_str, ver_rev, node->description_short);
|
|
|
|
#else
|
|
|
|
printf("%c%c %-14s %-14s\n", want_flag, status_flag, name_str, ver_rev);
|
|
|
|
#endif
|
|
|
|
}
|
|
|
|
free(ver_rev);
|
2001-09-21 10:00:51 +05:30
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2001-10-25 19:56:05 +05:30
|
|
|
#endif
|
2001-02-10 07:35:24 +05:30
|
|
|
|
2001-02-10 19:56:48 +05:30
|
|
|
extern int dpkg_main(int argc, char **argv)
|
2001-02-10 07:35:24 +05:30
|
|
|
{
|
2001-10-25 19:56:05 +05:30
|
|
|
deb_file_t **deb_file = xcalloc(1, sizeof(deb_file_t *));
|
2001-07-14 00:05:24 +05:30
|
|
|
char opt = 0;
|
|
|
|
int dpkg_opt = 0;
|
|
|
|
int deb_count = 0;
|
|
|
|
int i;
|
2001-10-25 19:56:05 +05:30
|
|
|
unsigned short state_default_new_want = STATE_WANT_INSTALL;
|
|
|
|
unsigned short state_default_new_flag = STATE_FLAG_REINSTREQ;
|
|
|
|
unsigned short state_default_new_status = STATE_STATUS_NOTINSTALLED;
|
|
|
|
|
|
|
|
while ((opt = getopt(argc, argv,
|
|
|
|
#ifdef BB_FEATURE_DPKG_LIST
|
|
|
|
"CF:ilPru")) != -1) {
|
|
|
|
#else
|
|
|
|
"CF:iPru")) != -1) {
|
|
|
|
#endif
|
2001-04-08 10:57:18 +05:30
|
|
|
switch (opt) {
|
2001-07-18 10:47:39 +05:30
|
|
|
case 'C': // equivalent to --configure in official dpkg
|
2001-10-25 19:56:05 +05:30
|
|
|
dpkg_opt |= DPKG_OPT_CONFIGURE | DPKG_OPT_PACKAGENAME;
|
2001-07-14 00:05:24 +05:30
|
|
|
break;
|
|
|
|
case 'F': // equivalent to --force in official dpkg
|
|
|
|
if (strcmp(optarg, "depends") == 0) {
|
2001-10-25 19:56:05 +05:30
|
|
|
dpkg_opt |= DPKG_OPT_FORCE_IGNORE_DEPENDS;
|
2001-07-14 00:05:24 +05:30
|
|
|
}
|
2001-04-08 10:57:18 +05:30
|
|
|
case 'i':
|
2001-10-25 19:56:05 +05:30
|
|
|
dpkg_opt |= DPKG_OPT_INSTALL | DPKG_OPT_FILENAME;
|
2001-04-08 10:57:18 +05:30
|
|
|
break;
|
2001-10-25 19:56:05 +05:30
|
|
|
#ifdef BB_FEATURE_DPKG_LIST
|
2001-07-14 00:05:24 +05:30
|
|
|
case 'l':
|
2001-10-25 19:56:05 +05:30
|
|
|
dpkg_opt |= DPKG_OPT_LIST_INSTALLED;
|
2001-09-21 10:00:51 +05:30
|
|
|
break;
|
2001-10-25 19:56:05 +05:30
|
|
|
#endif
|
2001-07-14 00:05:24 +05:30
|
|
|
case 'P':
|
2001-10-25 19:56:05 +05:30
|
|
|
dpkg_opt |= DPKG_OPT_PURGE | DPKG_OPT_PACKAGENAME;
|
|
|
|
state_default_new_want = STATE_WANT_PURGE;
|
2001-04-08 10:57:18 +05:30
|
|
|
break;
|
2001-07-14 00:05:24 +05:30
|
|
|
case 'r':
|
2001-10-25 19:56:05 +05:30
|
|
|
dpkg_opt |= DPKG_OPT_REMOVE | DPKG_OPT_PACKAGENAME;
|
|
|
|
state_default_new_want = STATE_WANT_DEINSTALL;
|
2001-07-14 00:05:24 +05:30
|
|
|
break;
|
|
|
|
case 'u': /* Equivalent to --unpack in official dpkg */
|
2001-10-25 19:56:05 +05:30
|
|
|
dpkg_opt |= DPKG_OPT_UNPACK | DPKG_OPT_FILENAME;
|
2001-04-08 10:57:18 +05:30
|
|
|
break;
|
|
|
|
default:
|
|
|
|
show_usage();
|
|
|
|
}
|
|
|
|
}
|
2001-10-25 19:56:05 +05:30
|
|
|
|
2001-09-21 10:00:51 +05:30
|
|
|
/* check for non-otion argument if expected */
|
2001-10-25 19:56:05 +05:30
|
|
|
if ((dpkg_opt == 0) || ((dpkg_opt & DPKG_OPT_FILENAME) && (dpkg_opt & DPKG_OPT_PACKAGENAME))) {
|
2001-07-14 00:05:24 +05:30
|
|
|
show_usage();
|
2001-09-21 10:00:51 +05:30
|
|
|
}
|
2001-07-14 00:05:24 +05:30
|
|
|
|
2001-10-25 19:56:05 +05:30
|
|
|
deb_initialise_hashtables(1);
|
2001-07-14 00:05:24 +05:30
|
|
|
index_status_file("/var/lib/dpkg/status");
|
|
|
|
|
2001-10-25 19:56:05 +05:30
|
|
|
#ifdef BB_FEATURE_DPKG_LIST
|
2001-09-21 10:00:51 +05:30
|
|
|
/* if the list action was given print the installed packages and exit */
|
2001-10-25 19:56:05 +05:30
|
|
|
if (dpkg_opt & DPKG_OPT_LIST_INSTALLED) {
|
2001-09-21 10:00:51 +05:30
|
|
|
list_packages();
|
|
|
|
}
|
2001-10-25 19:56:05 +05:30
|
|
|
#endif
|
|
|
|
|
2001-07-14 00:05:24 +05:30
|
|
|
/* Read arguments and store relevant info in structs */
|
2001-04-08 10:57:18 +05:30
|
|
|
while (optind < argc) {
|
2001-10-25 19:56:05 +05:30
|
|
|
const char *arg_name = argv[optind];
|
|
|
|
unsigned int node_num;
|
|
|
|
deb_file_t *tmp;
|
|
|
|
node_t *node;
|
|
|
|
|
|
|
|
tmp = (deb_file_t *) xcalloc(sizeof(deb_file_t), 1);
|
|
|
|
|
|
|
|
if (dpkg_opt & DPKG_OPT_FILENAME) {
|
|
|
|
tmp->filename = xstrdup(arg_name);
|
|
|
|
/* Extract the control file */
|
|
|
|
tmp->control_file = deb_extract(arg_name, stdout, (extract_control_tar_gz | extract_one_to_buffer), NULL, "./control");
|
|
|
|
if (tmp->control_file == NULL) {
|
|
|
|
error_msg("Couldnt extract control file from, ignoring package %s", arg_name);
|
|
|
|
optind++;
|
|
|
|
free(tmp->filename);
|
|
|
|
free(tmp);
|
2001-07-14 00:05:24 +05:30
|
|
|
continue;
|
|
|
|
}
|
2001-10-25 19:56:05 +05:30
|
|
|
node = parse_package_metadata(tmp->control_file);
|
|
|
|
|
|
|
|
if (node == NULL) {
|
|
|
|
error_msg_and_die("node was null\n");
|
|
|
|
} else {
|
|
|
|
node_num = search_node_ht(node, CMP_ANY);
|
|
|
|
node->state_want = state_default_new_want;
|
|
|
|
node->state_flag = state_default_new_flag;
|
|
|
|
node->state_status = state_default_new_status;
|
2001-07-14 00:05:24 +05:30
|
|
|
|
2001-10-25 19:56:05 +05:30
|
|
|
if (get_node_ht(node_num) == NULL) {
|
|
|
|
printf("Selecting previously deselected package %s\n", get_name_ht(node->name));
|
2001-10-04 10:52:42 +05:30
|
|
|
}
|
2001-10-25 19:56:05 +05:30
|
|
|
add_node(node, node_num);
|
2001-07-14 00:05:24 +05:30
|
|
|
}
|
2001-10-25 19:56:05 +05:30
|
|
|
} else {
|
|
|
|
/* It must be a package name */
|
|
|
|
node = initialise_node(arg_name);
|
|
|
|
node_num = search_node_ht(node, CMP_ANY);
|
|
|
|
free_node(node);
|
|
|
|
|
|
|
|
node = get_node_ht(node_num);
|
|
|
|
if (node == NULL) {
|
|
|
|
error_msg_and_die("Package %s is uninstalled or unknown\n", arg_name);
|
2001-07-14 00:05:24 +05:30
|
|
|
}
|
2001-10-25 19:56:05 +05:30
|
|
|
|
|
|
|
node->state_want = state_default_new_want;
|
2001-02-11 07:10:23 +05:30
|
|
|
|
2001-07-14 00:05:24 +05:30
|
|
|
/* check package status is "installed" */
|
2001-10-25 19:56:05 +05:30
|
|
|
if (dpkg_opt & DPKG_OPT_REMOVE) {
|
|
|
|
if ((node->state_status == STATE_STATUS_NOTINSTALLED) ||
|
|
|
|
(node->state_status == STATE_STATUS_CONFIGFILES)) {
|
|
|
|
error_msg_and_die("%s is already removed.", arg_name);
|
2001-07-14 00:05:24 +05:30
|
|
|
}
|
|
|
|
}
|
2001-10-25 19:56:05 +05:30
|
|
|
else if (dpkg_opt & DPKG_OPT_PURGE) {
|
|
|
|
if (node->state_status == STATE_STATUS_NOTINSTALLED) {
|
|
|
|
error_msg_and_die("%s is already purged.", arg_name);
|
2001-07-14 00:05:24 +05:30
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2001-10-25 19:56:05 +05:30
|
|
|
|
|
|
|
tmp->node = node_num;
|
|
|
|
deb_file = realloc(deb_file, sizeof(deb_file_t) * (deb_count + 1));
|
|
|
|
deb_file[deb_count] = tmp;
|
|
|
|
|
2001-07-14 00:05:24 +05:30
|
|
|
deb_count++;
|
2001-10-25 19:56:05 +05:30
|
|
|
deb_file[deb_count] = NULL;
|
|
|
|
|
2001-04-08 10:57:18 +05:30
|
|
|
optind++;
|
2001-02-10 07:35:24 +05:30
|
|
|
}
|
2001-02-11 07:10:23 +05:30
|
|
|
|
2001-10-25 19:56:05 +05:30
|
|
|
#if 0
|
2001-07-14 00:05:24 +05:30
|
|
|
/* Check that the deb file arguments are installable */
|
|
|
|
/* TODO: check dependencies before removing */
|
|
|
|
if ((dpkg_opt & dpkg_opt_force_ignore_depends) != dpkg_opt_force_ignore_depends) {
|
2001-10-25 19:56:05 +05:30
|
|
|
/* */
|
|
|
|
for (i = 0; i < deb_count; i++) {
|
|
|
|
/* add filename to list */
|
2001-07-14 00:05:24 +05:30
|
|
|
}
|
2001-04-08 10:57:18 +05:30
|
|
|
|
2001-10-25 19:56:05 +05:30
|
|
|
/* Sort packages into groups and add dependencies */
|
|
|
|
find_deps(package_name);
|
|
|
|
|
|
|
|
/* Check all packages in groups and sub groups are installed */
|
|
|
|
}
|
|
|
|
#endif
|
2001-07-14 00:05:24 +05:30
|
|
|
for (i = 0; i < deb_count; i++) {
|
|
|
|
/* Remove or purge packages */
|
2001-10-25 19:56:05 +05:30
|
|
|
if (dpkg_opt & DPKG_OPT_REMOVE) {
|
|
|
|
remove_package(deb_file[i]->node);
|
2001-07-14 00:05:24 +05:30
|
|
|
}
|
2001-10-25 19:56:05 +05:30
|
|
|
else if (dpkg_opt & DPKG_OPT_PURGE) {
|
|
|
|
purge_package(deb_file[i]->node);
|
2001-07-14 00:05:24 +05:30
|
|
|
}
|
2001-10-25 19:56:05 +05:30
|
|
|
else if (dpkg_opt & DPKG_OPT_UNPACK) {
|
2001-07-14 00:05:24 +05:30
|
|
|
unpack_package(deb_file[i]);
|
|
|
|
}
|
2001-10-25 19:56:05 +05:30
|
|
|
else if (dpkg_opt & DPKG_OPT_INSTALL) {
|
2001-07-14 00:05:24 +05:30
|
|
|
unpack_package(deb_file[i]);
|
|
|
|
configure_package(deb_file[i]);
|
|
|
|
}
|
2001-10-25 19:56:05 +05:30
|
|
|
else if (dpkg_opt & DPKG_OPT_CONFIGURE) {
|
2001-07-14 00:05:24 +05:30
|
|
|
configure_package(deb_file[i]);
|
|
|
|
}
|
|
|
|
}
|
2001-07-18 21:17:21 +05:30
|
|
|
|
2001-07-14 00:05:24 +05:30
|
|
|
write_status_file(deb_file);
|
|
|
|
|
2001-10-25 19:56:05 +05:30
|
|
|
if (deb_file != NULL) {
|
|
|
|
for (i = 0; i < deb_count; i++) {
|
|
|
|
free(deb_file[i]->control_file);
|
|
|
|
free(deb_file[i]->filename);
|
|
|
|
free(deb_file[i]);
|
2001-07-14 00:05:24 +05:30
|
|
|
}
|
2001-10-25 19:56:05 +05:30
|
|
|
free(deb_file);
|
2001-02-10 07:35:24 +05:30
|
|
|
}
|
2001-10-25 19:56:05 +05:30
|
|
|
free_hashtables();
|
2001-07-14 00:05:24 +05:30
|
|
|
|
2001-09-29 09:04:38 +05:30
|
|
|
return(EXIT_SUCCESS);
|
2001-02-15 02:53:06 +05:30
|
|
|
}
|
2001-07-14 00:05:24 +05:30
|
|
|
|