opkg: re-arrange source code into sub-directories
authorticktock35 <ticktock35@e8e0d7a0-c8d9-11dd-a880-a1081c7ac358>
Mon, 15 Dec 2008 04:25:08 +0000 (04:25 +0000)
committerticktock35 <ticktock35@e8e0d7a0-c8d9-11dd-a880-a1081c7ac358>
Mon, 15 Dec 2008 04:25:08 +0000 (04:25 +0000)
git-svn-id: http://opkg.googlecode.com/svn/trunk@33 e8e0d7a0-c8d9-11dd-a880-a1081c7ac358

160 files changed:
Makefile.am
args.c [deleted file]
args.h [deleted file]
conffile.c [deleted file]
conffile.h [deleted file]
conffile_list.c [deleted file]
conffile_list.h [deleted file]
configure.ac
file_util.c [deleted file]
file_util.h [deleted file]
hash_table.c [deleted file]
hash_table.h [deleted file]
includes.h [deleted file]
libopkg.c [deleted file]
libopkg.h [deleted file]
libopkg/Makefile.am [new file with mode: 0644]
libopkg/args.c [new file with mode: 0644]
libopkg/args.h [new file with mode: 0644]
libopkg/conffile.c [new file with mode: 0644]
libopkg/conffile.h [new file with mode: 0644]
libopkg/conffile_list.c [new file with mode: 0644]
libopkg/conffile_list.h [new file with mode: 0644]
libopkg/file_util.c [new file with mode: 0644]
libopkg/file_util.h [new file with mode: 0644]
libopkg/hash_table.c [new file with mode: 0644]
libopkg/hash_table.h [new file with mode: 0644]
libopkg/includes.h [new file with mode: 0644]
libopkg/libopkg.c [new file with mode: 0644]
libopkg/libopkg.h [new file with mode: 0644]
libopkg/md5.c [new file with mode: 0644]
libopkg/md5.h [new file with mode: 0644]
libopkg/nv_pair.c [new file with mode: 0644]
libopkg/nv_pair.h [new file with mode: 0644]
libopkg/nv_pair_list.c [new file with mode: 0644]
libopkg/nv_pair_list.h [new file with mode: 0644]
libopkg/opkg.c [new file with mode: 0644]
libopkg/opkg.h [new file with mode: 0644]
libopkg/opkg_cmd.c [new file with mode: 0644]
libopkg/opkg_cmd.h [new file with mode: 0644]
libopkg/opkg_conf.c [new file with mode: 0644]
libopkg/opkg_conf.h [new file with mode: 0644]
libopkg/opkg_configure.c [new file with mode: 0644]
libopkg/opkg_configure.h [new file with mode: 0644]
libopkg/opkg_download.c [new file with mode: 0644]
libopkg/opkg_download.h [new file with mode: 0644]
libopkg/opkg_extract_test.c [new file with mode: 0644]
libopkg/opkg_hash_test.c [new file with mode: 0644]
libopkg/opkg_install.c [new file with mode: 0644]
libopkg/opkg_install.h [new file with mode: 0644]
libopkg/opkg_message.c [new file with mode: 0644]
libopkg/opkg_message.h [new file with mode: 0644]
libopkg/opkg_remove.c [new file with mode: 0644]
libopkg/opkg_remove.h [new file with mode: 0644]
libopkg/opkg_state.c [new file with mode: 0644]
libopkg/opkg_state.h [new file with mode: 0644]
libopkg/opkg_upgrade.c [new file with mode: 0644]
libopkg/opkg_upgrade.h [new file with mode: 0644]
libopkg/opkg_utils.c [new file with mode: 0644]
libopkg/opkg_utils.h [new file with mode: 0644]
libopkg/pkg.c [new file with mode: 0644]
libopkg/pkg.h [new file with mode: 0644]
libopkg/pkg_depends.c [new file with mode: 0644]
libopkg/pkg_depends.h [new file with mode: 0644]
libopkg/pkg_dest.c [new file with mode: 0644]
libopkg/pkg_dest.h [new file with mode: 0644]
libopkg/pkg_dest_list.c [new file with mode: 0644]
libopkg/pkg_dest_list.h [new file with mode: 0644]
libopkg/pkg_extract.c [new file with mode: 0644]
libopkg/pkg_extract.h [new file with mode: 0644]
libopkg/pkg_hash.c [new file with mode: 0644]
libopkg/pkg_hash.h [new file with mode: 0644]
libopkg/pkg_parse.c [new file with mode: 0644]
libopkg/pkg_parse.h [new file with mode: 0644]
libopkg/pkg_src.c [new file with mode: 0644]
libopkg/pkg_src.h [new file with mode: 0644]
libopkg/pkg_src_list.c [new file with mode: 0644]
libopkg/pkg_src_list.h [new file with mode: 0644]
libopkg/pkg_vec.c [new file with mode: 0644]
libopkg/pkg_vec.h [new file with mode: 0644]
libopkg/sprintf_alloc.c [new file with mode: 0644]
libopkg/sprintf_alloc.h [new file with mode: 0644]
libopkg/str_list.c [new file with mode: 0644]
libopkg/str_list.h [new file with mode: 0644]
libopkg/str_util.c [new file with mode: 0644]
libopkg/str_util.h [new file with mode: 0644]
libopkg/user.c [new file with mode: 0644]
libopkg/user.h [new file with mode: 0644]
libopkg/void_list.c [new file with mode: 0644]
libopkg/void_list.h [new file with mode: 0644]
libopkg/xregex.c [new file with mode: 0644]
libopkg/xregex.h [new file with mode: 0644]
libopkg/xsystem.c [new file with mode: 0644]
libopkg/xsystem.h [new file with mode: 0644]
md5.c [deleted file]
md5.h [deleted file]
nv_pair.c [deleted file]
nv_pair.h [deleted file]
nv_pair_list.c [deleted file]
nv_pair_list.h [deleted file]
opkg-frontend.c [deleted file]
opkg.c [deleted file]
opkg.h [deleted file]
opkg_cmd.c [deleted file]
opkg_cmd.h [deleted file]
opkg_conf.c [deleted file]
opkg_conf.h [deleted file]
opkg_configure.c [deleted file]
opkg_configure.h [deleted file]
opkg_download.c [deleted file]
opkg_download.h [deleted file]
opkg_extract_test.c [deleted file]
opkg_hash_test.c [deleted file]
opkg_install.c [deleted file]
opkg_install.h [deleted file]
opkg_message.c [deleted file]
opkg_message.h [deleted file]
opkg_remove.c [deleted file]
opkg_remove.h [deleted file]
opkg_state.c [deleted file]
opkg_state.h [deleted file]
opkg_upgrade.c [deleted file]
opkg_upgrade.h [deleted file]
opkg_utils.c [deleted file]
opkg_utils.h [deleted file]
pkg.c [deleted file]
pkg.h [deleted file]
pkg_depends.c [deleted file]
pkg_depends.h [deleted file]
pkg_dest.c [deleted file]
pkg_dest.h [deleted file]
pkg_dest_list.c [deleted file]
pkg_dest_list.h [deleted file]
pkg_extract.c [deleted file]
pkg_extract.h [deleted file]
pkg_hash.c [deleted file]
pkg_hash.h [deleted file]
pkg_parse.c [deleted file]
pkg_parse.h [deleted file]
pkg_src.c [deleted file]
pkg_src.h [deleted file]
pkg_src_list.c [deleted file]
pkg_src_list.h [deleted file]
pkg_vec.c [deleted file]
pkg_vec.h [deleted file]
sprintf_alloc.c [deleted file]
sprintf_alloc.h [deleted file]
src/Makefile.am [new file with mode: 0644]
src/opkg-frontend.c [new file with mode: 0644]
str_list.c [deleted file]
str_list.h [deleted file]
str_util.c [deleted file]
str_util.h [deleted file]
user.c [deleted file]
user.h [deleted file]
void_list.c [deleted file]
void_list.h [deleted file]
xregex.c [deleted file]
xregex.h [deleted file]
xsystem.c [deleted file]
xsystem.h [deleted file]

index 256c254..69b61f0 100644 (file)
@@ -1,14 +1,11 @@
 #SUBDIRS = etc replace familiar libbb
-SUBDIRS = etc familiar libbb
+SUBDIRS =  etc familiar libbb libopkg src
 
 HOST_CPU=@host_cpu@
 BUILD_CPU=@build_cpu@
 OPKGLIBDIR=@opkglibdir@ 
 ALL_CFLAGS=-g -O -Wall -DHOST_CPU_STR=\"@host_cpu@\" -DBUILD_CPU=@build_cpu@ -DLIBDIR=\"@libdir@\" -DOPKGLIBDIR=\"@opkglibdir@\" -DDATADIR=\"@datadir@\"
 
-bin_PROGRAMS = opkg-cl
-
-lib_LTLIBRARIES = libopkg.la
 
 bin_SCRIPTS = update-alternatives
 
@@ -18,71 +15,7 @@ intercept_DATA = intercept/ldconfig intercept/depmod intercept/update-modules
 install-data-hook:
        chmod +x $(DESTDIR)$(datadir)/opkg/intercept/*
 
-# opkg_LDADD = libbb/libbb.a replace/libreplace.a
-
-#opkg_cl_LDADD = libopkg.la libbb/libbb.la replace/libreplace.a 
-opkg_cl_LDADD = libopkg.la libbb/libbb.la 
-
-libopkg_includedir=$(includedir)/libopkg
-
-libopkg_include_HEADERS= \
-       args.h \
-       conffile.h \
-       conffile_list.h \
-       config.h \
-       hash_table.h \
-       includes.h \
-       opkg_conf.h \
-       opkg.h \
-       opkg_message.h \
-       opkg_state.h \
-       nv_pair.h \
-       nv_pair_list.h \
-       pkg_depends.h \
-       pkg_dest.h \
-       pkg_dest_list.h \
-       pkg.h \
-       pkg_hash.h \
-       pkg_src.h \
-       pkg_src_list.h \
-       pkg_vec.h \
-       str_list.h \
-       void_list.h \
-       libopkg.h 
-
-#\ replace/replace.h
-
-#libopkg_la_LIBADD = libbb/libbb.la replace/libreplace.a
-libopkg_la_LIBADD = libbb/libbb.la $(CURL_LIBS) $(GPGME_LIBS)
-
-opkg_core_sources = args.c args.h opkg.c \
-                   user.c user.h 
-opkg_libcore_sources = args.c args.h libopkg.c libopkg.h opkg.h\
-                   user.c user.h opkg_state.c opkg_state.h
-opkg_cmd_sources = opkg_cmd.c opkg_cmd.h \
-                  opkg_configure.c opkg_configure.h \
-                  opkg_download.c opkg_download.h \
-                  opkg_install.c opkg_install.h \
-                  opkg_upgrade.c opkg_upgrade.h \
-                  opkg_remove.c opkg_remove.h
-opkg_db_sources = opkg_conf.c opkg_conf.h \
-                 opkg_utils.c opkg_utils.h pkg.c pkg.h hash_table.h \
-                 pkg_depends.c pkg_depends.h pkg_extract.c pkg_extract.h \
-                 hash_table.c pkg_hash.c pkg_hash.h pkg_parse.c pkg_parse.h \
-                 pkg_vec.c pkg_vec.h
-opkg_list_sources = conffile.c conffile.h conffile_list.c conffile_list.h \
-                   nv_pair.c nv_pair.h nv_pair_list.c nv_pair_list.h \
-                   pkg_dest.c pkg_dest.h pkg_dest_list.c pkg_dest_list.h \
-                   pkg_src.c pkg_src.h pkg_src_list.c pkg_src_list.h \
-                   str_list.c str_list.h void_list.c void_list.h
-opkg_util_sources = file_util.c file_util.h opkg_message.h opkg_message.c md5.c md5.h \
-                   sprintf_alloc.c sprintf_alloc.h str_util.c str_util.h \
-                   xregex.c xregex.h xsystem.c xsystem.h
-
-# opkg_SOURCES = $(opkg_core_sources) $(opkg_cmd_sources) $(opkg_db_sources) \
-#             $(opkg_util_sources) $(opkg_list_sources)
-
-EXTRA_DIST = opkg.c update-alternatives $(intercept_DATA)
+EXTRA_DIST = update-alternatives $(intercept_DATA)
 
 MAINTAINERCLEANFILES= \
        configure \
@@ -93,26 +26,5 @@ MAINTAINERCLEANFILES= \
        .Makefile.am.swp \
        aclocal.m4
 
-libopkg_la_SOURCES = $(opkg_libcore_sources) $(opkg_cmd_sources) $(opkg_db_sources) \
-              $(opkg_util_sources) $(opkg_list_sources)
-
-opkg_cl_SOURCES = opkg-frontend.c
-
-libopkg_la_CFLAGS = -DOPKG_LIB $(ALL_CFLAGS)  $(CURL_CFLAGS) $(GPGME_CFLAGS)
-
-opkg_CFLAGS = $(ALL_CFLAGS) $(CURL_CFLAGS) $(GPGME_CFLAGS)
-
-opkg_cl_CFLAGS = -DOPKG_LIB $(ALL_CFLAGS)
-
-noinst_PROGRAMS = opkg_hash_test opkg_extract_test
-
-opkg_hash_test_LDADD = libbb/libbb.la
-opkg_hash_test_SOURCES = opkg_hash_test.c $(opkg_db_sources) $(opkg_util_sources) $(opkg_list_sources)
-opkg_hash_test_CFLAGS = $(ALL_CFLAGS)
-
-opkg_extract_test_LDADD = libbb/libbb.la
-opkg_extract_test_SOURCES = opkg_extract_test.c $(opkg_db_sources) $(opkg_util_sources) $(opkg_list_sources)
-opkg_extract_test_CFLAGS = $(ALL_CFLAGS)
-
 package: all-recursive
        STRIPPROG=$(STRIP) familiar/rules INSTALL=$$PWD/install-sh  binary-arch
diff --git a/args.c b/args.c
deleted file mode 100644 (file)
index 99f3e12..0000000
--- a/args.c
+++ /dev/null
@@ -1,317 +0,0 @@
-/* args.c - parse command-line args
-  Carl D. Worth
-
-  Copyright 2001 University of Southern California
-  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, 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 General Public License for more details.
- */
-
-#include <getopt.h>
-#include <stdlib.h>
-#include <string.h>
-#include <unistd.h>
-
-#include "opkg.h"
-
-#include "config.h"
-#include "args.h"
-#include "sprintf_alloc.h"
-
-static void print_version(void);
-
-enum long_args_opt
-{
-     ARGS_OPT_FORCE_DEFAULTS = 129,
-     ARGS_OPT_FORCE_DEPENDS,
-     ARGS_OPT_FORCE_OVERWRITE,
-     ARGS_OPT_FORCE_DOWNGRADE,
-     ARGS_OPT_FORCE_REINSTALL,
-     ARGS_OPT_FORCE_REMOVAL_OF_DEPENDENT_PACKAGES,
-     ARGS_OPT_FORCE_REMOVAL_OF_ESSENTIAL_PACKAGES,
-     ARGS_OPT_FORCE_SPACE,
-     ARGS_OPT_NOACTION,
-     ARGS_OPT_NODEPS,
-     ARGS_OPT_VERBOSE_WGET,
-     ARGS_OPT_VERBOSITY,
-     ARGS_OPT_MULTIPLE_PROVIDERS
-};
-
-int args_init(args_t *args)
-{
-     char *conf_file_dir;
-
-     memset(args, 0, sizeof(args_t));
-
-     args->dest = ARGS_DEFAULT_DEST;
-
-     conf_file_dir = getenv("OPKG_CONF_DIR");
-     if (conf_file_dir == NULL || conf_file_dir[0] == '\0') {
-         conf_file_dir = ARGS_DEFAULT_CONF_FILE_DIR;
-     }
-     sprintf_alloc(&args->conf_file, "%s/%s", conf_file_dir,
-                  ARGS_DEFAULT_CONF_FILE_NAME);
-
-     args->force_defaults = ARGS_DEFAULT_FORCE_DEFAULTS;
-     args->force_depends = ARGS_DEFAULT_FORCE_DEPENDS;
-     args->force_overwrite = ARGS_DEFAULT_FORCE_OVERWRITE;
-     args->force_downgrade = ARGS_DEFAULT_FORCE_DOWNGRADE;
-     args->force_reinstall = ARGS_DEFAULT_FORCE_REINSTALL;
-     args->force_removal_of_dependent_packages = ARGS_DEFAULT_FORCE_REMOVAL_OF_DEPENDENT_PACKAGES;
-     args->force_removal_of_essential_packages = ARGS_DEFAULT_FORCE_REMOVAL_OF_ESSENTIAL_PACKAGES;
-     args->noaction = ARGS_DEFAULT_NOACTION;
-     args->nodeps = ARGS_DEFAULT_NODEPS;
-     args->verbose_wget = ARGS_DEFAULT_VERBOSE_WGET;
-     args->verbosity = ARGS_DEFAULT_VERBOSITY;
-     args->offline_root = ARGS_DEFAULT_OFFLINE_ROOT;
-     args->offline_root_pre_script_cmd = ARGS_DEFAULT_OFFLINE_ROOT_PRE_SCRIPT_CMD;
-     args->offline_root_post_script_cmd = ARGS_DEFAULT_OFFLINE_ROOT_POST_SCRIPT_CMD;
-     args->multiple_providers = 0;
-     args->nocheckfordirorfile = 0;
-     args->noreadfeedsfile = 0;
-
-     return 1;
-}
-
-void args_deinit(args_t *args)
-{
-     free(args->conf_file);
-     args->conf_file = NULL;
-}
-
-int args_parse(args_t *args, int argc, char *argv[])
-{
-     int c;
-     int option_index = 0;
-     int parse_err = 0;
-     static struct option long_options[] = {
-         {"query-all", 0, 0, 'A'},
-         {"conf-file", 1, 0, 'f'},
-         {"conf", 1, 0, 'f'},
-         {"dest", 1, 0, 'd'},
-         {"force-defaults", 0, 0, ARGS_OPT_FORCE_DEFAULTS},
-         {"force_defaults", 0, 0, ARGS_OPT_FORCE_DEFAULTS},
-         {"force-depends", 0, 0, ARGS_OPT_FORCE_DEPENDS},
-         {"force_depends", 0, 0, ARGS_OPT_FORCE_DEPENDS},
-         {"force-overwrite", 0, 0, ARGS_OPT_FORCE_OVERWRITE},
-         {"force_overwrite", 0, 0, ARGS_OPT_FORCE_OVERWRITE},
-         {"force_downgrade", 0, 0, ARGS_OPT_FORCE_DOWNGRADE},
-         {"force-downgrade", 0, 0, ARGS_OPT_FORCE_DOWNGRADE},
-         {"force-reinstall", 0, 0, ARGS_OPT_FORCE_REINSTALL},
-         {"force_reinstall", 0, 0, ARGS_OPT_FORCE_REINSTALL},
-         {"force-space", 0, 0, ARGS_OPT_FORCE_SPACE},
-         {"force_space", 0, 0, ARGS_OPT_FORCE_SPACE},
-         {"recursive", 0, 0,
-          ARGS_OPT_FORCE_REMOVAL_OF_DEPENDENT_PACKAGES},
-         {"force-removal-of-dependent-packages", 0, 0,
-          ARGS_OPT_FORCE_REMOVAL_OF_DEPENDENT_PACKAGES},
-         {"force_removal_of_dependent_packages", 0, 0,
-          ARGS_OPT_FORCE_REMOVAL_OF_DEPENDENT_PACKAGES},
-         {"force-removal-of-essential-packages", 0, 0,
-          ARGS_OPT_FORCE_REMOVAL_OF_ESSENTIAL_PACKAGES},
-         {"force_removal_of_essential_packages", 0, 0,
-          ARGS_OPT_FORCE_REMOVAL_OF_ESSENTIAL_PACKAGES},
-         {"multiple-providers", 0, 0, ARGS_OPT_MULTIPLE_PROVIDERS},
-         {"multiple_providers", 0, 0, ARGS_OPT_MULTIPLE_PROVIDERS},
-         {"noaction", 0, 0, ARGS_OPT_NOACTION},
-         {"nodeps", 0, 0, ARGS_OPT_NODEPS},
-         {"offline", 1, 0, 'o'},
-         {"offline-root", 1, 0, 'o'},
-         {"test", 0, 0, ARGS_OPT_NOACTION},
-         {"tmp-dir", 1, 0, 't'},
-         {"verbose-wget", 0, 0, ARGS_OPT_VERBOSE_WGET},
-         {"verbose_wget", 0, 0, ARGS_OPT_VERBOSE_WGET},
-         {"verbosity", 2, 0, 'V'},
-         {"version", 0, 0, 'v'},
-         {0, 0, 0, 0}
-     };
-
-     while (1) {
-         c = getopt_long_only(argc, argv, "Ad:f:no:t:vV:", long_options, &option_index);
-         if (c == -1)
-              break;
-
-         switch (c) {
-         case 'A':
-              args->query_all = 1;
-              break;
-         case 'd':
-              args->dest = optarg;
-              break;
-         case 'f':
-              free(args->conf_file);
-              args->conf_file = strdup(optarg);
-              break;
-         case 'o':
-              args->offline_root = optarg;
-              break;
-         case 'n':
-              args->noaction = 1;
-              break;
-         case 't':
-              args->tmp_dir = strdup(optarg);
-              break;
-         case 'v':
-              print_version();
-              exit(0);
-         case 'V':
-         case ARGS_OPT_VERBOSITY:
-              if (optarg)
-                   args->verbosity = atoi(optarg);
-              else
-                   args->verbosity += 1;
-              break;
-         case ARGS_OPT_FORCE_DEFAULTS:
-              args->force_defaults = 1;
-              break;
-         case ARGS_OPT_FORCE_DEPENDS:
-              args->force_depends = 1;
-              break;
-         case ARGS_OPT_FORCE_OVERWRITE:
-              args->force_overwrite = 1;
-              break;
-         case ARGS_OPT_FORCE_DOWNGRADE:
-              args->force_downgrade = 1;
-              break;
-         case ARGS_OPT_FORCE_REINSTALL:
-              args->force_reinstall = 1;
-              break;
-         case ARGS_OPT_FORCE_REMOVAL_OF_ESSENTIAL_PACKAGES:
-              args->force_removal_of_essential_packages = 1;
-              break;
-         case ARGS_OPT_FORCE_REMOVAL_OF_DEPENDENT_PACKAGES:
-              args->force_removal_of_dependent_packages = 1;
-              break;
-         case ARGS_OPT_FORCE_SPACE:
-              args->force_space = 1;
-              break;
-         case ARGS_OPT_VERBOSE_WGET:
-              args->verbose_wget = 1;
-              break;
-         case ARGS_OPT_MULTIPLE_PROVIDERS:
-              args->multiple_providers = 1;
-              break;
-         case ARGS_OPT_NODEPS:
-              args->nodeps = 1;
-              break;
-         case ARGS_OPT_NOACTION:
-              args->noaction = 1;
-              break;
-         case ':':
-              parse_err++;
-              break;
-         case '?':
-              parse_err++;
-              break;
-         default:
-              printf("Confusion: getopt_long returned %d\n", c);
-         }
-     }
-    
-     if (parse_err) {
-         return -parse_err;
-     } else {
-         return optind;
-     }
-}
-
-void args_usage(char *complaint)
-{
-     if (complaint) {
-         fprintf(stderr, "opkg: %s\n", complaint);
-     }
-     print_version();
-     fprintf(stderr, "usage: opkg [options...] sub-command [arguments...]\n");
-     fprintf(stderr, "where sub-command is one of:\n");
-    
-     fprintf(stderr, "\nPackage Manipulation:\n");
-     fprintf(stderr, "\tupdate                 Update list of available packages\n");
-     fprintf(stderr, "\tupgrade                        Upgrade all installed packages to latest version\n");
-     fprintf(stderr, "\tinstall <pkg>          Download and install <pkg> (and dependencies)\n");
-     fprintf(stderr, "\tinstall <file.ipk>     Install package <file.ipk>\n");
-     fprintf(stderr, "\tconfigure [<pkg>]      Configure unpacked packages\n");
-     fprintf(stderr, "\tremove <pkg|regexp>    Remove package <pkg|packages following regexp>\n");
-     fprintf(stderr, "\tflag <flag> <pkg> ...  Flag package(s) <pkg>\n");
-     fprintf(stderr, "\t <flag>=hold|noprune|user|ok|installed|unpacked (one per invocation)   \n");
-    
-     fprintf(stderr, "\nInformational Commands:\n");
-     fprintf(stderr, "\tlist                   List available packages and descriptions\n");
-     fprintf(stderr, "\tlist_installed         List all and only the installed packages and description \n");
-     fprintf(stderr, "\tfiles <pkg>            List all files belonging to <pkg>\n");
-     fprintf(stderr, "\tsearch <file|regexp>           Search for a package providing <file>\n");
-#ifndef OPKG_LIB
-     fprintf(stderr, "\tinfo [pkg|regexp [<field>]]    Display all/some info fields for <pkg> or all\n");
-     fprintf(stderr, "\tstatus [pkg|regexp [<field>]]  Display all/some status fields for <pkg> or all\n");
-#else
-     fprintf(stderr, "\tinfo [pkg|regexp]              Display all info for <pkg>\n");
-     fprintf(stderr, "\tstatus [pkg|regexp]            Display all status for <pkg>\n");
-#endif
-     fprintf(stderr, "\tdownload <pkg>         Download <pkg> to current directory.\n");
-     fprintf(stderr, "\tcompare_versions <v1> <op> <v2>\n");
-     fprintf(stderr, "\t                          compare versions using <= < > >= = << >>\n");
-     fprintf(stderr, "\tprint_architecture      prints the architecture.\n");
-     fprintf(stderr, "\tprint_installation_architecture\n");
-     fprintf(stderr, "\twhatdepends [-A] [pkgname|pat]+\n");
-     fprintf(stderr, "\twhatdependsrec [-A] [pkgname|pat]+\n");
-     fprintf(stderr, "\twhatprovides [-A] [pkgname|pat]+\n");
-     fprintf(stderr, "\twhatconflicts [-A] [pkgname|pat]+\n");
-     fprintf(stderr, "\twhatreplaces [-A] [pkgname|pat]+\n");
-     fprintf(stderr, "\t                        prints the installation architecture.\n");    
-     fprintf(stderr, "\nOptions:\n");
-     fprintf(stderr, "\t-A                      Query all packages with whatdepends, whatprovides, whatreplaces, whatconflicts\n"); 
-     fprintf(stderr, "\t-V <level>               Set verbosity level to <level>. If no value is\n");
-     fprintf(stderr, "\t--verbosity <level>      provided increase verbosity by one. Verbosity levels:\n");
-     fprintf(stderr, "\t                         0 errors only\n");
-     fprintf(stderr, "\t                         1 normal messages (default)\n");
-     fprintf(stderr, "\t                         2 informative messages\n");
-     fprintf(stderr, "\t                         3 debug output\n");
-     fprintf(stderr, "\t-f <conf_file>         Use <conf_file> as the opkg configuration file\n");
-     fprintf(stderr, "\t-conf <conf_file>      Default configuration file location\n");
-     fprintf(stderr, "                         is %s/%s\n", ARGS_DEFAULT_CONF_FILE_DIR, ARGS_DEFAULT_CONF_FILE_NAME);
-     fprintf(stderr, "\t-d <dest_name>         Use <dest_name> as the the root directory for\n");
-     fprintf(stderr, "\t-dest <dest_name>      package installation, removal, upgrading.\n");
-     fprintf(stderr, "                         <dest_name> should be a defined dest name from\n");
-     fprintf(stderr, "                         the configuration file, (but can also be a\n");
-     fprintf(stderr, "                         directory name in a pinch).\n");
-     fprintf(stderr, "\t-o <offline_root>      Use <offline_root> as the root directory for\n");
-     fprintf(stderr, "\t-offline <offline_root>        offline installation of packages.\n");
-     fprintf(stderr, "\t-verbose_wget          more wget messages\n");
-    
-     fprintf(stderr, "\tForce Options (use when opkg is too smart for its own good):\n");
-     fprintf(stderr, "\t-force-depends         Make dependency checks warnings instead of errors\n");
-     fprintf(stderr, "\t                               Install/remove package in spite of failed dependences\n");
-     fprintf(stderr, "\t-force-defaults                Use default options for questions asked by opkg.\n");
-     fprintf(stderr, "                         (no prompts). Note that this will not prevent\n");
-     fprintf(stderr, "                         package installation scripts from prompting.\n");
-     fprintf(stderr, "\t-force-reinstall       Allow opkg to reinstall a package.\n");
-     fprintf(stderr, "\t-force-overwrite       Allow opkg to overwrite files from another package during an install.\n");
-     fprintf(stderr, "\t-force-downgrade       Allow opkg to downgrade packages.\n");
-     fprintf(stderr, "\t-force_space            Install even if there does not seem to be enough space.\n");
-     fprintf(stderr, "\t-noaction               No action -- test only\n");
-     fprintf(stderr, "\t-nodeps                 Do not follow dependences\n");
-     fprintf(stderr, "\t-force-removal-of-dependent-packages\n");
-     fprintf(stderr, "\t-recursive             Allow opkg to remove package and all that depend on it.\n");
-     fprintf(stderr, "\t-test                   No action -- test only\n");
-     fprintf(stderr, "\t-t                     Specify tmp-dir.\n");
-     fprintf(stderr, "\t--tmp-dir              Specify tmp-dir.\n");
-     fprintf(stderr, "\n");
-     fprintf(stderr, "\tregexp could be something like 'pkgname*' '*file*' or similar\n");
-     fprintf(stderr, "\teg: opkg info 'libstd*'  or opkg search '*libop*' or opkg remove 'libncur*'\n");
-     /* -force-removal-of-essential-packages   Let opkg remove essential packages. 
-       Using this option is almost guaranteed to break your system, hence this option
-       is not even advertised in the usage statement. */
-     exit(1);
-}
-
-static void print_version(void)
-{
-     fprintf(stderr, "opkg version %s\n", VERSION);
-}
diff --git a/args.h b/args.h
deleted file mode 100644 (file)
index a470778..0000000
--- a/args.h
+++ /dev/null
@@ -1,72 +0,0 @@
-/* args.h - parse command-line args
-
-  Carl D. Worth
-
-  Copyright 2001 University of Southern California
-  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, 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 General Public License for more details.
-*/
-
-#ifndef ARGS_H
-#define ARGS_H
-
-struct args
-{
-    char *conf_file;
-    char *dest;
-    char *tmp_dir;
-    int force_defaults;
-    int force_depends;
-    int force_overwrite;
-    int force_downgrade;
-    int force_reinstall;
-    int force_removal_of_essential_packages;
-    int force_removal_of_dependent_packages;
-    int force_space;
-    int noaction;
-    int nodeps;
-    int multiple_providers;
-    int query_all;
-    int verbose_wget;
-    int verbosity;
-    int nocheckfordirorfile;
-    int noreadfeedsfile;
-    char *offline_root;
-    char *offline_root_pre_script_cmd;
-    char *offline_root_post_script_cmd;
-};
-typedef struct args args_t;
-
-#define ARGS_DEFAULT_CONF_FILE_DIR "/etc"
-#define ARGS_DEFAULT_CONF_FILE_NAME "opkg.conf"
-#define ARGS_DEFAULT_DEST NULL
-#define ARGS_DEFAULT_FORCE_DEFAULTS 0
-#define ARGS_DEFAULT_FORCE_DEPENDS 0
-#define ARGS_DEFAULT_FORCE_OVERWRITE 0 
-#define ARGS_DEFAULT_FORCE_DOWNGRADE 0 
-#define ARGS_DEFAULT_FORCE_REINSTALL 0
-#define ARGS_DEFAULT_FORCE_REMOVAL_OF_ESSENTIAL_PACKAGES 0
-#define ARGS_DEFAULT_FORCE_REMOVAL_OF_DEPENDENT_PACKAGES 0
-#define ARGS_DEFAULT_FORCE_SPACE 0
-#define ARGS_DEFAULT_OFFLINE_ROOT NULL
-#define ARGS_DEFAULT_OFFLINE_ROOT_PRE_SCRIPT_CMD NULL
-#define ARGS_DEFAULT_OFFLINE_ROOT_POST_SCRIPT_CMD NULL
-#define ARGS_DEFAULT_NOACTION 0
-#define ARGS_DEFAULT_NODEPS 0
-#define ARGS_DEFAULT_VERBOSE_WGET 0
-#define ARGS_DEFAULT_VERBOSITY 1
-
-int args_init(args_t *args);
-void args_deinit(args_t *args);
-int args_parse(args_t *args, int argc, char *argv[]);
-void args_usage(char *complaint);
-
-#endif
diff --git a/conffile.c b/conffile.c
deleted file mode 100644 (file)
index 5f41cc1..0000000
+++ /dev/null
@@ -1,64 +0,0 @@
-/* conffile.c - the itsy package management system
-
-   Carl D. Worth
-
-   Copyright (C) 2001 University of Southern California
-
-   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, 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
-   General Public License for more details.
-*/
-
-#include <string.h>
-#include <stdlib.h>
-
-#include "opkg.h"
-#include "opkg_message.h"
-
-#include "conffile.h"
-#include "file_util.h"
-#include "sprintf_alloc.h"
-
-int conffile_init(conffile_t *conffile, const char *file_name, const char *md5sum)
-{
-    return nv_pair_init(conffile, file_name, md5sum);
-}
-
-void conffile_deinit(conffile_t *conffile)
-{
-    nv_pair_deinit(conffile);
-}
-
-int conffile_has_been_modified(opkg_conf_t *conf, conffile_t *conffile)
-{
-    char *md5sum;
-    char *filename = conffile->name;
-    char *root_filename;
-    int ret;
-
-    if (conffile->value == NULL) {
-        opkg_message(conf, OPKG_NOTICE, "%s: conffile %s has no md5sum\n", __FUNCTION__, conffile->name);
-        return 1;
-    }
-
-    root_filename = root_filename_alloc(conf, filename);
-
-    md5sum = file_md5sum_alloc(root_filename);
-
-    ret = strcmp(md5sum, conffile->value);
-    if (ret) {
-      opkg_message(conf, OPKG_NOTICE, "%s: conffile %s: \t\nold md5=%s \t\nnew md5=%s\n", __FUNCTION__,
-              conffile->name, md5sum, conffile->value);
-    }
-
-    free(root_filename);
-    free(md5sum);
-
-    return ret;
-}
diff --git a/conffile.h b/conffile.h
deleted file mode 100644 (file)
index 130d1d8..0000000
+++ /dev/null
@@ -1,30 +0,0 @@
-/* conffile.h - the itsy package management system
-
-   Carl D. Worth
-
-   Copyright (C) 2001 University of Southern California
-
-   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, 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
-   General Public License for more details.
-*/
-
-#ifndef CONFFILE_H
-#define CONFFILE_H
-
-#include "nv_pair.h"
-
-typedef struct nv_pair conffile_t;
-
-int conffile_init(conffile_t *conffile, const char *file_name, const char *md5sum);
-void conffile_deinit(conffile_t *conffile);
-int conffile_has_been_modified(struct opkg_conf *conf, conffile_t *conffile);
-
-#endif
-
diff --git a/conffile_list.c b/conffile_list.c
deleted file mode 100644 (file)
index 27d48d5..0000000
+++ /dev/null
@@ -1,47 +0,0 @@
-/* conffile_list.c - the itsy package management system
-
-   Carl D. Worth
-
-   Copyright (C) 2001 University of Southern California
-
-   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, 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
-   General Public License for more details.
-*/
-
-#include "opkg.h"
-
-#include "conffile_list.h"
-
-int conffile_list_init(conffile_list_t *list)
-{
-    return nv_pair_list_init(list);
-}
-
-void conffile_list_deinit(conffile_list_t *list)
-{
-    nv_pair_list_deinit(list);
-}
-
-conffile_t *conffile_list_append(conffile_list_t *list, const char *file_name,
-                        const char *md5sum)
-{
-    return nv_pair_list_append(list, file_name, md5sum);
-}
-
-int conffile_list_push(conffile_list_t *list, conffile_t *data)
-{
-    return nv_pair_list_push(list, data);
-}
-
-conffile_list_elt_t *conffile_list_pop(conffile_list_t *list)
-{
-    return nv_pair_list_pop(list);
-}
-
diff --git a/conffile_list.h b/conffile_list.h
deleted file mode 100644 (file)
index a5daac9..0000000
+++ /dev/null
@@ -1,36 +0,0 @@
-/* conffile_list.h - the itsy package management system
-
-   Carl D. Worth
-
-   Copyright (C) 2001 University of Southern California
-
-   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, 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
-   General Public License for more details.
-*/
-
-#ifndef CONFFILE_LIST_H
-#define CONFFILE_LIST_H
-
-#include "conffile.h"
-#include "nv_pair_list.h"
-
-typedef struct nv_pair_list_elt conffile_list_elt_t;
-typedef struct nv_pair_list conffile_list_t;
-
-int conffile_list_init(conffile_list_t *list);
-void conffile_list_deinit(conffile_list_t *list);
-
-conffile_t *conffile_list_append(conffile_list_t *list, const char *name,
-                              const char *root_dir);
-int conffile_list_push(conffile_list_t *list, conffile_t *data);
-conffile_list_elt_t *conffile_list_pop(conffile_list_t *list);
-
-#endif
-
index 3dd5dd9..c98db77 100644 (file)
@@ -1,7 +1,7 @@
 # Process this file with autoconf to produce a configure script
-AC_INIT(opkg.c)
+AC_INIT(libopkg/opkg.c)
 AM_INIT_AUTOMAKE([opkg], [0.99.163])
-AM_CONFIG_HEADER(config.h)
+AM_CONFIG_HEADER(libopkg/config.h)
 
 AC_CANONICAL_HOST
 
@@ -126,4 +126,16 @@ fi
 
 AC_SUBST(opkglibdir)
 
-AC_OUTPUT(Makefile etc/Makefile familiar/Makefile familiar/control familiar/control-unstripped familiar/libopkg-control  familiar/libopkg-dev-control libbb/Makefile libopkg.pc opkg.h)
+AC_OUTPUT(
+    Makefile
+    libopkg/Makefile
+    src/Makefile
+    etc/Makefile
+    familiar/Makefile
+    familiar/control
+    familiar/control-unstripped
+    familiar/libopkg-control
+    familiar/libopkg-dev-control
+    libbb/Makefile
+    libopkg.pc
+    opkg.h)
diff --git a/file_util.c b/file_util.c
deleted file mode 100644 (file)
index da8a1cd..0000000
+++ /dev/null
@@ -1,177 +0,0 @@
-/* file_util.c - convenience routines for common stat operations
-
-   Carl D. Worth
-
-   Copyright (C) 2001 University of Southern California
-
-   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, 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
-   General Public License for more details.
-*/
-
-#include "opkg.h"
-#include <sys/types.h>
-#include <sys/stat.h>
-
-#include "sprintf_alloc.h"
-#include "file_util.h"
-#include "md5.h"
-#include "libbb/libbb.h"
-#undef strlen
-
-int file_exists(const char *file_name)
-{
-    int err;
-    struct stat stat_buf;
-
-    err = stat(file_name, &stat_buf);
-    if (err == 0) {
-       return 1;
-    } else {
-       return 0;
-    }
-}
-
-int file_is_dir(const char *file_name)
-{
-    int err;
-    struct stat stat_buf;
-
-    err = stat(file_name, &stat_buf);
-    if (err) {
-       return 0;
-    }
-
-    return S_ISDIR(stat_buf.st_mode);
-}
-
-/* read a single line from a file, stopping at a newline or EOF.
-   If a newline is read, it will appear in the resulting string.
-   Return value is a malloc'ed char * which should be freed at
-   some point by the caller.
-
-   Return value is NULL if the file is at EOF when called.
-*/
-#define FILE_READ_LINE_BUF_SIZE 1024
-char *file_read_line_alloc(FILE *file)
-{
-    char buf[FILE_READ_LINE_BUF_SIZE];
-    int buf_len;
-    char *line = NULL;
-    int line_size = 0;
-
-    memset(buf, 0, FILE_READ_LINE_BUF_SIZE);
-    while (fgets(buf, FILE_READ_LINE_BUF_SIZE, file)) {
-       buf_len = strlen(buf);
-       if (line) {
-           line_size += buf_len;
-           line = realloc(line, line_size);
-           if (line == NULL) {
-               fprintf(stderr, "%s: out of memory\n", __FUNCTION__);
-               break;
-           }
-           strcat(line, buf);
-       } else {
-           line_size = buf_len + 1;
-           line = strdup(buf);
-       }
-       if (buf[buf_len - 1] == '\n') {
-           break;
-       }
-    }
-
-    return line;
-}
-
-int file_move(const char *src, const char *dest)
-{
-    int err;
-
-    err = rename(src, dest);
-
-    if (err && errno == EXDEV) {
-       err = file_copy(src, dest);
-       unlink(src);
-    } else if (err) {
-       fprintf(stderr, "%s: ERROR: failed to rename %s to %s: %s\n",
-               __FUNCTION__, src, dest, strerror(errno));
-    }
-
-    return err;
-}
-
-/* I put these here to keep libbb dependencies from creeping all over
-   the opkg code */
-int file_copy(const char *src, const char *dest)
-{
-    int err;
-
-    err = copy_file(src, dest, FILEUTILS_FORCE | FILEUTILS_PRESERVE_STATUS);
-    if (err) {
-       fprintf(stderr, "%s: ERROR: failed to copy %s to %s\n",
-               __FUNCTION__, src, dest);
-    }
-
-    return err;
-}
-
-int file_mkdir_hier(const char *path, long mode)
-{
-    return make_directory(path, mode, FILEUTILS_RECUR);
-}
-
-char *file_md5sum_alloc(const char *file_name)
-{
-    static const int md5sum_bin_len = 16;
-    static const int md5sum_hex_len = 32;
-
-    static const unsigned char bin2hex[16] = {
-       '0', '1', '2', '3',
-       '4', '5', '6', '7',
-       '8', '9', 'a', 'b',
-       'c', 'd', 'e', 'f'
-    };
-
-    int i, err;
-    FILE *file;
-    unsigned char *md5sum_hex;
-    unsigned char md5sum_bin[md5sum_bin_len];
-
-    md5sum_hex = malloc(md5sum_hex_len + 1);
-    if (md5sum_hex == NULL) {
-       fprintf(stderr, "%s: out of memory\n", __FUNCTION__);
-       return strdup("");
-    }
-
-    file = fopen(file_name, "r");
-    if (file == NULL) {
-       fprintf(stderr, "%s: Failed to open file %s: %s\n",
-               __FUNCTION__, file_name, strerror(errno));
-       return strdup("");
-    }
-
-    err = md5_stream(file, md5sum_bin);
-    if (err) {
-       fprintf(stderr, "%s: ERROR computing md5sum for %s: %s\n",
-               __FUNCTION__, file_name, strerror(err));
-       return strdup("");
-    }
-
-    fclose(file);
-
-    for (i=0; i < md5sum_bin_len; i++) {
-       md5sum_hex[i*2] = bin2hex[md5sum_bin[i] >> 4];
-       md5sum_hex[i*2+1] = bin2hex[md5sum_bin[i] & 0xf];
-    }
-    
-    md5sum_hex[md5sum_hex_len] = '\0';
-    
-    return md5sum_hex;
-}
-
diff --git a/file_util.h b/file_util.h
deleted file mode 100644 (file)
index bcfb3cb..0000000
+++ /dev/null
@@ -1,29 +0,0 @@
-/* file_util.h - convenience routines for common file operations
-
-   Carl D. Worth
-
-   Copyright (C) 2001 University of Southern California
-
-   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, 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
-   General Public License for more details.
-*/
-
-#ifndef FILE_UTIL_H
-#define FILE_UTIL_H
-
-int file_exists(const char *file_name);
-int file_is_dir(const char *file_name);
-char *file_read_line_alloc(FILE *file);
-int file_move(const char *src, const char *dest);
-int file_copy(const char *src, const char *dest);
-int file_mkdir_hier(const char *path, long mode);
-char *file_md5sum_alloc(const char *file_name);
-
-#endif
diff --git a/hash_table.c b/hash_table.c
deleted file mode 100644 (file)
index 41877c2..0000000
+++ /dev/null
@@ -1,155 +0,0 @@
-/* hash.c - hash tables for opkg
-
-   Steven M. Ayer, Jamey Hicks
-   
-   Copyright (C) 2002 Compaq Computer Corporation
-
-   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, 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
-   General Public License for more details.
-*/
-
-#include <errno.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include "hash_table.h"
-#include "opkg_message.h"
-
-
-static int hash_index(hash_table_t *hash, const char *pkg_name);
-static int rotating(const char *key, int len, int prime);
-
-static int hash_index(hash_table_t *hash, const char *pkg_name)
-{
-    return rotating(pkg_name, strlen(pkg_name), hash->n_entries);
-}
-  
-static int rotating(const char *key, int len, int prime)
-{
-    unsigned int hash, i;
-    for (hash=len, i=0; i<len; ++i)
-       hash = (hash<<4)^(hash>>28)^key[i];
-    return (hash % prime);
-}
-
-
-/*
- * this is an open table keyed by strings
- */
-int hash_table_init(const char *name, hash_table_t *hash, int len)
-{
-    static int primes_table[] = {
-       379, 761, 983, 1423, 2711, 3361, 3931, 4679, 5519, 6701, 9587,
-       19471, 23143, 33961, 46499, 49727, 99529, 0
-    };
-    int *picker;
-
-    if (hash->entries != NULL) {
-       /* we have been here already */
-       return 0;
-    }
-
-    hash->name = name;
-    hash->entries = NULL;
-    hash->n_entries = 0;
-    hash->hash_entry_key = NULL;
-
-    picker = primes_table;
-    while(*picker && (*picker++ < len));
-    if(!*picker)
-       fprintf(stderr, "%s: primes table might not be big enough (! << %d)\n", __FUNCTION__, len);
-    --picker;
-
-    hash->n_entries = *picker;
-    hash->entries = (hash_entry_t *)calloc(hash->n_entries, sizeof(hash_entry_t));
-    if (hash->entries == NULL) {
-       fprintf(stderr, "%s: Out of memory.\n", __FUNCTION__);
-       return ENOMEM;
-    }
-    return 0;
-}
-
-void hash_table_deinit(hash_table_t *hash)
-{
-    free(hash->entries);
-    hash->entries = NULL;
-    hash->n_entries = 0;
-}
-
-void *hash_table_get(hash_table_t *hash, const char *key)
-{
-  int ndx= hash_index(hash, key);
-  hash_entry_t *hash_entry = hash->entries + ndx;
-  while (hash_entry) 
-  {
-    if (hash_entry->key) 
-    {
-      if (strcmp(key, hash_entry->key) == 0) {
-         // opkg_message(NULL, OPKG_DEBUG, "Function: %s. Key found for '%s' \n", __FUNCTION__, key);
-        return hash_entry->data;
-      }
-    }
-    hash_entry = hash_entry->next;
-  }
-  return NULL;
-}
-
-int hash_table_insert(hash_table_t *hash, const char *key, void *value)
-{
-     int ndx= hash_index(hash, key);
-     hash_entry_t *hash_entry = hash->entries + ndx;
-     if (0) opkg_message(NULL, OPKG_DEBUG2, "Function: %s. Inserting in hash for '%s' \n", __FUNCTION__, key);
-     if (hash_entry->key) {
-         if (strcmp(hash_entry->key, key) == 0) {
-              /* alread in table, update the value */
-               if (0) opkg_message(NULL, OPKG_DEBUG2, "Function: %s. Value already in hash for '%s' \n", __FUNCTION__, key);
-              hash_entry->data = value;
-              return 0;
-         } else {
-              /* 
-               * if this is a collision, we have to go to the end of the ll,
-               * then add a new entry
-               * before we can hook up the value
-               */
-               if (0) opkg_message(NULL, OPKG_DEBUG2, "Function: %s. Value already in hash by collision for '%s' \n", __FUNCTION__, key);
-              while (hash_entry->next)
-                   hash_entry = hash_entry->next;
-              hash_entry->next = (hash_entry_t *)malloc(sizeof(hash_entry_t));
-              if (!hash_entry->next) {
-                   return -ENOMEM;
-              }
-              hash_entry = hash_entry->next;
-              hash_entry->next = NULL;
-         }
-     }
-     hash->n_elements++;
-     hash_entry->key = strdup(key);
-     hash_entry->data = value;
-
-     return 0;
-}
-
-
-void hash_table_foreach(hash_table_t *hash, void (*f)(const char *key, void *entry, void *data), void *data)
-{ 
-    int i;
-    if (!hash || !f)
-       return;
-
-    for (i = 0; i < hash->n_entries; i++) {
-       hash_entry_t *hash_entry = (hash->entries + i);
-       do {
-           if(hash_entry->key) {
-               f(hash_entry->key, hash_entry->data, data);
-           }
-       } while((hash_entry = hash_entry->next));
-    }
-}
-
diff --git a/hash_table.h b/hash_table.h
deleted file mode 100644 (file)
index 388a966..0000000
+++ /dev/null
@@ -1,44 +0,0 @@
-/* hash.h - hash tables for opkg
-
-   Steven M. Ayer, Jamey Hicks
-   
-   Copyright (C) 2002 Compaq Computer Corporation
-
-   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, 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
-   General Public License for more details.
-*/
-
-#ifndef _HASH_TABLE_H_
-#define _HASH_TABLE_H_
-
-typedef struct hash_entry hash_entry_t;
-typedef struct hash_table hash_table_t;
-
-struct hash_entry {
-  const char * key;
-  void * data;
-  struct hash_entry * next;
-};
-
-struct hash_table {
-  const char *name; 
-  hash_entry_t * entries;  
-  int n_entries; /* number of buckets */
-  int n_elements;
-  const char * (*hash_entry_key)(void * data);
-};
-
-int hash_table_init(const char *name, hash_table_t *hash, int len);
-void hash_table_deinit(hash_table_t *hash);
-void *hash_table_get(hash_table_t *hash, const char *key);
-int hash_table_insert(hash_table_t *hash, const char *key, void *value);
-void hash_table_foreach(hash_table_t *hash, void (*f)(const char *key, void *entry, void *data), void *data);
-
-#endif /* _HASH_TABLE_H_ */
diff --git a/includes.h b/includes.h
deleted file mode 100644 (file)
index 5a67001..0000000
+++ /dev/null
@@ -1,53 +0,0 @@
-#ifndef INCLUDES_H
-#define INCLUDES_H
-
-#include <stdio.h>
-
-#if STDC_HEADERS
-# include <stdlib.h>
-# include <stdarg.h>
-# include <stddef.h>
-# include <ctype.h>
-# include <errno.h>
-#else
-# if HAVE_STDLIB_H
-#  include <stdlib.h>
-# endif
-#endif
-
-#if HAVE_REGEX_H
-# include <regex.h>
-#endif
-
-#if HAVE_STRING_H
-# if !STDC_HEADERS && HAVE_MEMORY_H
-#  include <memory.h>
-# endif
-/* XXX: What's the right way to pick up GNU's strndup declaration? */
-# if __GNUC__
-#   define __USE_GNU 1
-# endif
-# include <string.h>
-# undef __USE_GNU
-#endif
-
-#if HAVE_STRINGS_H
-# include <strings.h>
-#endif
-
-#if HAVE_SYS_STAT_H
-# include <sys/stat.h>
-#endif
-
-#if HAVE_SYS_WAIT_H
-# include <sys/wait.h>
-#endif
-
-#if HAVE_UNISTD_H
-# include <sys/types.h>
-# include <unistd.h>
-#endif
-
-// #include "replace/replace.h"
-
-#endif
diff --git a/libopkg.c b/libopkg.c
deleted file mode 100644 (file)
index c57ad0a..0000000
--- a/libopkg.c
+++ /dev/null
@@ -1,527 +0,0 @@
-/* opkglib.c - the itsy package management system
-
-   Florina Boor
-
-   Copyright (C) 2003 kernel concepts
-
-   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, 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
-   General Public License for more details.
-*/
-
-#ifdef OPKG_LIB
-
-#include "opkg.h"
-#include "includes.h"
-#include "libopkg.h"
-
-#include "args.h"
-#include "opkg_conf.h"
-#include "opkg_cmd.h"
-#include "file_util.h"
-
-
-
-opkg_message_callback opkg_cb_message = NULL;
-opkg_response_callback opkg_cb_response = NULL;
-opkg_status_callback opkg_cb_status = NULL;
-opkg_list_callback opkg_cb_list = NULL;
-
-
-int
-opkg_init (opkg_message_callback mcall, 
-           opkg_response_callback rcall,
-           args_t * args)
-{
-       opkg_cb_message = mcall;
-       opkg_cb_response = rcall;
-
-       args_init (args);
-
-       return 0;
-}
-
-
-int
-opkg_deinit (args_t * args)
-{
-       args_deinit (args);
-       opkg_cb_message = NULL;
-       opkg_cb_response = NULL;
-
-       /* place other cleanup stuff here */
-
-       return 0;
-}
-
-
-int
-opkg_packages_list(args_t *args, 
-                   const char *packages, 
-                   opkg_list_callback cblist,
-                   void *userdata)
-{
-       opkg_cmd_t *cmd;
-       opkg_conf_t opkg_conf;
-       int err;
-
-       err = opkg_conf_init (&opkg_conf, args);
-       if (err)
-       {
-               return err;
-       }
-
-       opkg_cb_list = cblist;
-       /* we need to do this because of static declarations, 
-        * maybe a good idea to change */
-       cmd = opkg_cmd_find ("list");
-       if (packages)
-               err = opkg_cmd_exec (cmd, &opkg_conf, 1, &packages, userdata);
-       else
-               err = opkg_cmd_exec (cmd, &opkg_conf, 0, NULL, userdata);
-       opkg_cb_list = NULL;
-       opkg_conf_deinit (&opkg_conf);
-       return (err);
-}
-
-
-int
-opkg_packages_status(args_t *args,
-                     const char *packages,
-                     opkg_status_callback cbstatus,
-                     void *userdata)
-{
-       opkg_cmd_t *cmd;
-       opkg_conf_t opkg_conf;
-       int err;
-
-       err = opkg_conf_init (&opkg_conf, args);
-       if (err)
-       {
-               return err;
-       }
-
-       opkg_cb_status = cbstatus;
-
-       /* we need to do this because of static declarations,
-        * maybe a good idea to change */
-       cmd = opkg_cmd_find ("status");
-       if (packages)
-               err = opkg_cmd_exec (cmd, &opkg_conf, 1, &packages, userdata);
-       else
-               err = opkg_cmd_exec (cmd, &opkg_conf, 0, NULL, userdata);
-
-       opkg_cb_status = NULL;
-       opkg_conf_deinit (&opkg_conf);
-       return (err);
-}
-
-
-int
-opkg_packages_info(args_t *args,
-                   const char *packages,
-                   opkg_status_callback cbstatus,
-                   void *userdata)
-{
-       opkg_cmd_t *cmd;
-       opkg_conf_t opkg_conf;
-       int err;
-
-       err = opkg_conf_init (&opkg_conf, args);
-       if (err)
-       {
-               return err;
-       }
-
-       opkg_cb_status = cbstatus;
-
-       /* we need to do this because of static declarations,
-        * maybe a good idea to change */
-       cmd = opkg_cmd_find ("info");
-       if (packages)
-               err = opkg_cmd_exec (cmd, &opkg_conf, 1, &packages, userdata);
-       else
-               err = opkg_cmd_exec (cmd, &opkg_conf, 0, NULL, userdata);
-
-       opkg_cb_status = NULL;
-       opkg_conf_deinit (&opkg_conf);
-       return (err);
-}
-
-
-int
-opkg_packages_install (args_t * args, const char *name)
-{
-       opkg_cmd_t *cmd;
-       opkg_conf_t opkg_conf;
-       int err;
-
-       /* this error should be handled in application */
-       if (!name || !strlen (name))
-               return (-1);
-
-       err = opkg_conf_init (&opkg_conf, args);
-       if (err)
-       {
-               return err;
-       }
-
-       /* we need to do this because of static declarations,
-        * maybe a good idea to change */
-       cmd = opkg_cmd_find ("install");
-       err = opkg_cmd_exec (cmd, &opkg_conf, 1, &name, NULL);
-
-       opkg_conf_deinit(&opkg_conf);
-       return (err);
-}
-
-
-int
-opkg_packages_remove(args_t *args, const char *name, int purge)
-{
-       opkg_cmd_t *cmd;
-       opkg_conf_t opkg_conf;
-       int err;
-
-       /* this error should be handled in application */
-       if (!name || !strlen (name))
-               return (-1);
-
-       err = opkg_conf_init (&opkg_conf, args);
-       if (err)
-       {
-               return err;
-       }
-
-       /* we need to do this because of static declarations, 
-        * maybe a good idea to change */
-       if (purge)
-               cmd = opkg_cmd_find ("purge");
-       else
-               cmd = opkg_cmd_find ("remove");
-
-       err = opkg_cmd_exec (cmd, &opkg_conf, 1, &name, NULL);
-       
-       opkg_conf_deinit(&opkg_conf);
-       return (err);
-}
-
-
-int 
-opkg_lists_update(args_t *args)
-{
-       opkg_cmd_t *cmd;
-       opkg_conf_t opkg_conf;
-       int err;
-
-       err = opkg_conf_init (&opkg_conf, args);
-       if (err)
-       {
-               return err;
-       }
-
-       /* we need to do this because of static declarations, 
-        * maybe a good idea to change */
-       cmd = opkg_cmd_find ("update");
-
-       err = opkg_cmd_exec (cmd, &opkg_conf, 0, NULL, NULL);
-       
-       opkg_conf_deinit(&opkg_conf);
-       return (err);
-}
-
-
-int 
-opkg_packages_upgrade(args_t *args)
-{
-       opkg_cmd_t *cmd;
-       opkg_conf_t opkg_conf;
-       int err;
-
-       err = opkg_conf_init (&opkg_conf, args);
-       if (err)
-       {
-               return err;
-       }
-
-       /* we need to do this because of static declarations, 
-        * maybe a good idea to change */
-       cmd = opkg_cmd_find ("upgrade");
-
-       err = opkg_cmd_exec (cmd, &opkg_conf, 0, NULL, NULL);
-       
-       opkg_conf_deinit(&opkg_conf);
-       return (err);
-}
-
-
-int
-opkg_packages_download (args_t * args, const char *name)
-{
-       opkg_cmd_t *cmd;
-       opkg_conf_t opkg_conf;
-       int err;
-
-       /* this error should be handled in application */
-       if (!name || !strlen (name))
-               return (-1);
-
-       err = opkg_conf_init (&opkg_conf, args);
-       if (err)
-       {
-               return err;
-       }
-
-       /* we need to do this because of static declarations,
-        * maybe a good idea to change */
-       cmd = opkg_cmd_find ("download");
-       err = opkg_cmd_exec (cmd, &opkg_conf, 1, &name, NULL);
-
-       opkg_conf_deinit(&opkg_conf);
-       return (err);
-}
-
-
-int
-opkg_package_files(args_t *args, 
-                   const char *name, 
-                   opkg_list_callback cblist,
-                   void *userdata)
-{
-       opkg_cmd_t *cmd;
-       opkg_conf_t opkg_conf;
-       int err;
-
-       /* this error should be handled in application */
-       if (!name || !strlen (name))
-               return (-1);
-
-       err = opkg_conf_init (&opkg_conf, args);
-       if (err)
-       {
-               return err;
-       }
-
-       opkg_cb_list = cblist;
-       
-       /* we need to do this because of static declarations, 
-        * maybe a good idea to change */
-       cmd = opkg_cmd_find ("files");
-
-       err = opkg_cmd_exec (cmd, &opkg_conf, 1, &name, userdata);
-       
-       opkg_cb_list = NULL;
-       opkg_conf_deinit(&opkg_conf);
-       return (err);
-}
-
-
-int 
-opkg_file_search(args_t *args, 
-                const char *file,
-                               opkg_list_callback cblist,
-                void *userdata)
-{
-       opkg_cmd_t *cmd;
-       opkg_conf_t opkg_conf;
-       int err;
-       
-       /* this error should be handled in application */
-       if (!file || !strlen (file))
-               return (-1);
-
-       err = opkg_conf_init (&opkg_conf, args);
-       if (err)
-       {
-               return err;
-       }
-
-       opkg_cb_list = cblist;
-
-       /* we need to do this because of static declarations, 
-        * maybe a good idea to change */
-       cmd = opkg_cmd_find ("search");
-       err = opkg_cmd_exec (cmd, &opkg_conf, 1, &file, userdata);
-       
-       opkg_cb_list = NULL;
-       opkg_conf_deinit(&opkg_conf);
-       return(err);
-}
-
-
-int 
-opkg_file_what(args_t *args, const char *file, const char* command)
-{
-       opkg_cmd_t *cmd;
-       opkg_conf_t opkg_conf;
-       int err;
-       
-       /* this error should be handled in application */
-       if (!file || !strlen (file))
-               return (-1);
-
-       err = opkg_conf_init (&opkg_conf, args);
-       if (err)
-       {
-               return err;
-       }
-
-       /* we need to do this because of static declarations, 
-        * maybe a good idea to change */
-       cmd = opkg_cmd_find (command);
-       err = opkg_cmd_exec (cmd, &opkg_conf, 1, &file, NULL);
-       
-       opkg_conf_deinit(&opkg_conf);
-       return(err);
-}
-
-#define opkg_package_whatdepends(args,file) opkg_file_what(args,file,"whatdepends")
-#define opkg_package_whatrecommends(args, file) opkg_file_what(args,file,"whatrecommends")
-#define opkg_package_whatprovides(args, file) opkg_file_what(args,file,"whatprovides")
-#define opkg_package_whatconflicts(args, file) opkg_file_what(args,file,"whatconflicts")
-#define opkg_package_whatreplaces(args, file) opkg_file_what(args,file,"whatreplaces")
-
-
-int default_opkg_message_callback(opkg_conf_t *conf, message_level_t level, 
-                                 char *msg)
-{
-     if (conf && (conf->verbosity < level)) {
-         return 0;
-     } else {
-#ifdef OPKG_LIB
-          if ( level == OPKG_ERROR ){
-             push_error_list(&error_list, msg); 
-//          printf(msg);
-          } else
-#endif
-            printf(msg);
-     }
-     return 0;
-}
-
-int default_opkg_list_callback(char *name, char *desc, char *version, 
-                              pkg_state_status_t status, void *userdata)
-{
-     if (desc)
-         printf("%s - %s - %s\n", name, version, desc);
-     else
-         printf("%s - %s\n", name, version);
-     return 0;
-}
-
-int default_opkg_files_callback(char *name, char *desc, char *version,
-                   pkg_state_status_t status, void *userdata)
-{
-     if (desc)
-         printf("%s\n", desc);
-     return 0;
-}
-
-int default_opkg_status_callback(char *name, int istatus, char *desc,
-                                void *userdata)
-{
-     printf("%s\n", desc);
-     return 0;
-}
-
-char* default_opkg_response_callback(char *question)
-{
-     char *response = NULL;
-     printf(question);
-     fflush(stdout);
-     do {
-         response = (char *)file_read_line_alloc(stdin);
-     } while (response == NULL);
-     return response;
-}
-
-/* This is used for backward compatibility */
-int
-opkg_op (int argc, char *argv[])
-{
-       int err, optind;
-       args_t args;
-       char *cmd_name;
-       opkg_cmd_t *cmd;
-       opkg_conf_t opkg_conf;
-
-       args_init (&args);
-
-       optind = args_parse (&args, argc, argv);
-       if (optind == argc || optind < 0)
-       {
-               args_usage ("opkg must have one sub-command argument");
-       }
-
-       cmd_name = argv[optind++];
-/* Pigi: added a flag to disable the checking of structures if the command does not need to 
-         read anything from there.
-*/
-        if ( !strcmp(cmd_name,"print-architecture") ||
-             !strcmp(cmd_name,"print_architecture") ||
-             !strcmp(cmd_name,"print-installation-architecture") ||
-             !strcmp(cmd_name,"print_installation_architecture") )
-           args.nocheckfordirorfile = 1;
-
-/* Pigi: added a flag to disable the reading of feed files  if the command does not need to 
-         read anything from there.
-*/
-        if ( !strcmp(cmd_name,"flag") ||
-             !strcmp(cmd_name,"configure") ||
-             !strcmp(cmd_name,"remove") ||
-             !strcmp(cmd_name,"files") ||
-             !strcmp(cmd_name,"search") ||
-             !strcmp(cmd_name,"compare_versions") ||
-             !strcmp(cmd_name,"compare-versions") ||
-             !strcmp(cmd_name,"list_installed") ||
-             !strcmp(cmd_name,"list-installed") ||
-             !strcmp(cmd_name,"status") )
-           args.noreadfeedsfile = 1;
-
-
-       err = opkg_conf_init (&opkg_conf, &args);
-       if (err)
-       {
-               return err;
-       }
-
-       args_deinit (&args);
-
-       opkg_cb_message = default_opkg_message_callback;
-       opkg_cb_response = default_opkg_response_callback;
-       opkg_cb_status = default_opkg_status_callback;
-       if ( strcmp(cmd_name, "files")==0)
-            opkg_cb_list = default_opkg_files_callback;
-       else
-            opkg_cb_list = default_opkg_list_callback;
-
-       cmd = opkg_cmd_find (cmd_name);
-       if (cmd == NULL)
-       {
-               fprintf (stderr, "%s: unknown sub-command %s\n", argv[0],
-                        cmd_name);
-               args_usage (NULL);
-       }
-
-       if (cmd->requires_args && optind == argc)
-       {
-               fprintf (stderr,
-                        "%s: the ``%s'' command requires at least one argument\n",
-                        __FUNCTION__, cmd_name);
-               args_usage (NULL);
-       }
-
-       err = opkg_cmd_exec (cmd, &opkg_conf, argc - optind, (const char **) (argv + optind), NULL);
-
-       opkg_conf_deinit (&opkg_conf);
-
-       return err;
-}
-
-#endif /* OPKG_LIB */
diff --git a/libopkg.h b/libopkg.h
deleted file mode 100644 (file)
index 3430e1c..0000000
--- a/libopkg.h
+++ /dev/null
@@ -1,94 +0,0 @@
-/* opkglib.h - the itsy package management system
-
-   Florian Boor <florian.boor@kernelconcepts.de>
-
-   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, 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
-   General Public License for more details.
-*/
-
-#ifndef OPKGLIB_H
-#define OPKGLIB_H
-
-#ifdef HAVE_CONFIG_H
-#include "config.h"
-#endif
-
-
-#ifdef OPKG_LIB
-
-#include "opkg_conf.h"
-#include "opkg_message.h"
-#include "opkg_state.h"
-
-#include "args.h"
-#include "pkg.h"
-
-typedef int (*opkg_message_callback)(opkg_conf_t *conf, message_level_t level, 
-       char *msg);
-typedef int (*opkg_list_callback)(char *name, char *desc, char *version, 
-       pkg_state_status_t status, void *userdata);
-typedef int (*opkg_status_callback)(char *name, int istatus, char *desc,
-       void *userdata);
-typedef char* (*opkg_response_callback)(char *question);
-typedef void (*opkg_download_progress_callback)(int percent, char *url);
-typedef void (*opkg_state_changed_callback)(opkg_state_t state, const char *data);
-
-extern int opkg_op(int argc, char *argv[]); /* opkglib.c */
-extern int opkg_init (opkg_message_callback mcall, 
-                      opkg_response_callback rcall,
-                                         args_t * args);
-
-extern int opkg_deinit (args_t *args);
-extern int opkg_packages_list(args_t *args, 
-                              const char *packages, 
-                              opkg_list_callback cblist,
-                              void *userdata);
-extern int opkg_packages_status(args_t *args, 
-                                const char *packages, 
-                                opkg_status_callback cbstatus,
-                                                               void *userdata);
-extern int opkg_packages_info(args_t *args,
-                              const char *packages,
-                              opkg_status_callback cbstatus,
-                              void *userdata);
-extern int opkg_packages_install(args_t *args, const char *name);
-extern int opkg_packages_remove(args_t *args, const char *name, int purge);
-extern int opkg_lists_update(args_t *args);
-extern int opkg_packages_upgrade(args_t *args);
-extern int opkg_packages_download(args_t *args, const char *name);
-extern int opkg_package_files(args_t *args,
-                              const char *name,
-                                                         opkg_list_callback cblist,
-                                                         void *userdata);
-extern int opkg_file_search(args_t *args,
-                            const char *file,
-                                                       opkg_list_callback cblist,
-                                                       void *userdata);
-extern int opkg_package_whatdepends(args_t *args, const char *file);
-extern int opkg_package_whatrecommends(args_t *args, const char *file);
-extern int opkg_package_whatprovides(args_t *args, const char *file);
-extern int opkg_package_whatconflicts(args_t *args, const char *file);
-extern int opkg_package_whatreplaces(args_t *args, const char *file);
-
-extern opkg_message_callback opkg_cb_message; /* opkglib.c */
-extern opkg_response_callback opkg_cb_response;
-extern opkg_status_callback opkg_cb_status;
-extern opkg_list_callback opkg_cb_list;
-extern opkg_download_progress_callback opkg_cb_download_progress; /* opkg_download.c */
-extern opkg_state_changed_callback opkg_cb_state_changed; /* opkg_state.c */
-
-extern void push_error_list(struct errlist **errors,char * msg);
-extern void reverse_error_list(struct errlist **errors);
-extern void free_error_list();
-
-#endif
-
-
-#endif
diff --git a/libopkg/Makefile.am b/libopkg/Makefile.am
new file mode 100644 (file)
index 0000000..ad4de4d
--- /dev/null
@@ -0,0 +1,76 @@
+
+ALL_CFLAGS=-g -O -Wall -DHOST_CPU_STR=\"@host_cpu@\" -DBUILD_CPU=@build_cpu@ -DLIBDIR=\"@libdir@\" -DOPKGLIBDIR=\"@opkglibdir@\" -DDATADIR=\"@datadir@\" -I$(top_builddir)
+
+libopkg_includedir=$(includedir)/libopkg
+
+libopkg_include_HEADERS= \
+       args.h \
+       conffile.h \
+       conffile_list.h \
+       config.h \
+       hash_table.h \
+       includes.h \
+       opkg_conf.h \
+       opkg.h \
+       opkg_message.h \
+       opkg_state.h \
+       nv_pair.h \
+       nv_pair_list.h \
+       pkg_depends.h \
+       pkg_dest.h \
+       pkg_dest_list.h \
+       pkg.h \
+       pkg_hash.h \
+       pkg_src.h \
+       pkg_src_list.h \
+       pkg_vec.h \
+       str_list.h \
+       void_list.h \
+       libopkg.h 
+
+libopkg_la_LIBADD = $(top_builddir)/libbb/libbb.la $(CURL_LIBS) $(GPGME_LIBS)
+
+opkg_core_sources = args.c args.h opkg.c \
+                   user.c user.h 
+opkg_libcore_sources = args.c args.h libopkg.c libopkg.h opkg.h\
+                   user.c user.h opkg_state.c opkg_state.h
+opkg_cmd_sources = opkg_cmd.c opkg_cmd.h \
+                  opkg_configure.c opkg_configure.h \
+                  opkg_download.c opkg_download.h \
+                  opkg_install.c opkg_install.h \
+                  opkg_upgrade.c opkg_upgrade.h \
+                  opkg_remove.c opkg_remove.h
+opkg_db_sources = opkg_conf.c opkg_conf.h \
+                 opkg_utils.c opkg_utils.h pkg.c pkg.h hash_table.h \
+                 pkg_depends.c pkg_depends.h pkg_extract.c pkg_extract.h \
+                 hash_table.c pkg_hash.c pkg_hash.h pkg_parse.c pkg_parse.h \
+                 pkg_vec.c pkg_vec.h
+opkg_list_sources = conffile.c conffile.h conffile_list.c conffile_list.h \
+                   nv_pair.c nv_pair.h nv_pair_list.c nv_pair_list.h \
+                   pkg_dest.c pkg_dest.h pkg_dest_list.c pkg_dest_list.h \
+                   pkg_src.c pkg_src.h pkg_src_list.c pkg_src_list.h \
+                   str_list.c str_list.h void_list.c void_list.h
+opkg_util_sources = file_util.c file_util.h opkg_message.h opkg_message.c md5.c md5.h \
+                   sprintf_alloc.c sprintf_alloc.h str_util.c str_util.h \
+                   xregex.c xregex.h xsystem.c xsystem.h
+
+libopkg_la_SOURCES = \
+       $(opkg_libcore_sources) \
+       $(opkg_cmd_sources) $(opkg_db_sources) \
+       $(opkg_util_sources) $(opkg_list_sources)
+
+libopkg_la_CFLAGS = -DOPKG_LIB $(ALL_CFLAGS)  $(CURL_CFLAGS) $(GPGME_CFLAGS)
+lib_LTLIBRARIES = libopkg.la
+
+
+noinst_PROGRAMS = opkg_hash_test opkg_extract_test
+
+opkg_hash_test_LDADD = $(top_builddir)/libbb/libbb.la
+opkg_hash_test_SOURCES = opkg_hash_test.c $(opkg_db_sources) $(opkg_util_sources) $(opkg_list_sources)
+opkg_hash_test_CFLAGS = $(ALL_CFLAGS)
+
+opkg_extract_test_LDADD = $(top_builddir)/libbb/libbb.la
+opkg_extract_test_SOURCES = opkg_extract_test.c $(opkg_db_sources) $(opkg_util_sources) $(opkg_list_sources)
+opkg_extract_test_CFLAGS = $(ALL_CFLAGS)
+
+
diff --git a/libopkg/args.c b/libopkg/args.c
new file mode 100644 (file)
index 0000000..99f3e12
--- /dev/null
@@ -0,0 +1,317 @@
+/* args.c - parse command-line args
+  Carl D. Worth
+
+  Copyright 2001 University of Southern California
+  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, 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 General Public License for more details.
+ */
+
+#include <getopt.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+
+#include "opkg.h"
+
+#include "config.h"
+#include "args.h"
+#include "sprintf_alloc.h"
+
+static void print_version(void);
+
+enum long_args_opt
+{
+     ARGS_OPT_FORCE_DEFAULTS = 129,
+     ARGS_OPT_FORCE_DEPENDS,
+     ARGS_OPT_FORCE_OVERWRITE,
+     ARGS_OPT_FORCE_DOWNGRADE,
+     ARGS_OPT_FORCE_REINSTALL,
+     ARGS_OPT_FORCE_REMOVAL_OF_DEPENDENT_PACKAGES,
+     ARGS_OPT_FORCE_REMOVAL_OF_ESSENTIAL_PACKAGES,
+     ARGS_OPT_FORCE_SPACE,
+     ARGS_OPT_NOACTION,
+     ARGS_OPT_NODEPS,
+     ARGS_OPT_VERBOSE_WGET,
+     ARGS_OPT_VERBOSITY,
+     ARGS_OPT_MULTIPLE_PROVIDERS
+};
+
+int args_init(args_t *args)
+{
+     char *conf_file_dir;
+
+     memset(args, 0, sizeof(args_t));
+
+     args->dest = ARGS_DEFAULT_DEST;
+
+     conf_file_dir = getenv("OPKG_CONF_DIR");
+     if (conf_file_dir == NULL || conf_file_dir[0] == '\0') {
+         conf_file_dir = ARGS_DEFAULT_CONF_FILE_DIR;
+     }
+     sprintf_alloc(&args->conf_file, "%s/%s", conf_file_dir,
+                  ARGS_DEFAULT_CONF_FILE_NAME);
+
+     args->force_defaults = ARGS_DEFAULT_FORCE_DEFAULTS;
+     args->force_depends = ARGS_DEFAULT_FORCE_DEPENDS;
+     args->force_overwrite = ARGS_DEFAULT_FORCE_OVERWRITE;
+     args->force_downgrade = ARGS_DEFAULT_FORCE_DOWNGRADE;
+     args->force_reinstall = ARGS_DEFAULT_FORCE_REINSTALL;
+     args->force_removal_of_dependent_packages = ARGS_DEFAULT_FORCE_REMOVAL_OF_DEPENDENT_PACKAGES;
+     args->force_removal_of_essential_packages = ARGS_DEFAULT_FORCE_REMOVAL_OF_ESSENTIAL_PACKAGES;
+     args->noaction = ARGS_DEFAULT_NOACTION;
+     args->nodeps = ARGS_DEFAULT_NODEPS;
+     args->verbose_wget = ARGS_DEFAULT_VERBOSE_WGET;
+     args->verbosity = ARGS_DEFAULT_VERBOSITY;
+     args->offline_root = ARGS_DEFAULT_OFFLINE_ROOT;
+     args->offline_root_pre_script_cmd = ARGS_DEFAULT_OFFLINE_ROOT_PRE_SCRIPT_CMD;
+     args->offline_root_post_script_cmd = ARGS_DEFAULT_OFFLINE_ROOT_POST_SCRIPT_CMD;
+     args->multiple_providers = 0;
+     args->nocheckfordirorfile = 0;
+     args->noreadfeedsfile = 0;
+
+     return 1;
+}
+
+void args_deinit(args_t *args)
+{
+     free(args->conf_file);
+     args->conf_file = NULL;
+}
+
+int args_parse(args_t *args, int argc, char *argv[])
+{
+     int c;
+     int option_index = 0;
+     int parse_err = 0;
+     static struct option long_options[] = {
+         {"query-all", 0, 0, 'A'},
+         {"conf-file", 1, 0, 'f'},
+         {"conf", 1, 0, 'f'},
+         {"dest", 1, 0, 'd'},
+         {"force-defaults", 0, 0, ARGS_OPT_FORCE_DEFAULTS},
+         {"force_defaults", 0, 0, ARGS_OPT_FORCE_DEFAULTS},
+         {"force-depends", 0, 0, ARGS_OPT_FORCE_DEPENDS},
+         {"force_depends", 0, 0, ARGS_OPT_FORCE_DEPENDS},
+         {"force-overwrite", 0, 0, ARGS_OPT_FORCE_OVERWRITE},
+         {"force_overwrite", 0, 0, ARGS_OPT_FORCE_OVERWRITE},
+         {"force_downgrade", 0, 0, ARGS_OPT_FORCE_DOWNGRADE},
+         {"force-downgrade", 0, 0, ARGS_OPT_FORCE_DOWNGRADE},
+         {"force-reinstall", 0, 0, ARGS_OPT_FORCE_REINSTALL},
+         {"force_reinstall", 0, 0, ARGS_OPT_FORCE_REINSTALL},
+         {"force-space", 0, 0, ARGS_OPT_FORCE_SPACE},
+         {"force_space", 0, 0, ARGS_OPT_FORCE_SPACE},
+         {"recursive", 0, 0,
+          ARGS_OPT_FORCE_REMOVAL_OF_DEPENDENT_PACKAGES},
+         {"force-removal-of-dependent-packages", 0, 0,
+          ARGS_OPT_FORCE_REMOVAL_OF_DEPENDENT_PACKAGES},
+         {"force_removal_of_dependent_packages", 0, 0,
+          ARGS_OPT_FORCE_REMOVAL_OF_DEPENDENT_PACKAGES},
+         {"force-removal-of-essential-packages", 0, 0,
+          ARGS_OPT_FORCE_REMOVAL_OF_ESSENTIAL_PACKAGES},
+         {"force_removal_of_essential_packages", 0, 0,
+          ARGS_OPT_FORCE_REMOVAL_OF_ESSENTIAL_PACKAGES},
+         {"multiple-providers", 0, 0, ARGS_OPT_MULTIPLE_PROVIDERS},
+         {"multiple_providers", 0, 0, ARGS_OPT_MULTIPLE_PROVIDERS},
+         {"noaction", 0, 0, ARGS_OPT_NOACTION},
+         {"nodeps", 0, 0, ARGS_OPT_NODEPS},
+         {"offline", 1, 0, 'o'},
+         {"offline-root", 1, 0, 'o'},
+         {"test", 0, 0, ARGS_OPT_NOACTION},
+         {"tmp-dir", 1, 0, 't'},
+         {"verbose-wget", 0, 0, ARGS_OPT_VERBOSE_WGET},
+         {"verbose_wget", 0, 0, ARGS_OPT_VERBOSE_WGET},
+         {"verbosity", 2, 0, 'V'},
+         {"version", 0, 0, 'v'},
+         {0, 0, 0, 0}
+     };
+
+     while (1) {
+         c = getopt_long_only(argc, argv, "Ad:f:no:t:vV:", long_options, &option_index);
+         if (c == -1)
+              break;
+
+         switch (c) {
+         case 'A':
+              args->query_all = 1;
+              break;
+         case 'd':
+              args->dest = optarg;
+              break;
+         case 'f':
+              free(args->conf_file);
+              args->conf_file = strdup(optarg);
+              break;
+         case 'o':
+              args->offline_root = optarg;
+              break;
+         case 'n':
+              args->noaction = 1;
+              break;
+         case 't':
+              args->tmp_dir = strdup(optarg);
+              break;
+         case 'v':
+              print_version();
+              exit(0);
+         case 'V':
+         case ARGS_OPT_VERBOSITY:
+              if (optarg)
+                   args->verbosity = atoi(optarg);
+              else
+                   args->verbosity += 1;
+              break;
+         case ARGS_OPT_FORCE_DEFAULTS:
+              args->force_defaults = 1;
+              break;
+         case ARGS_OPT_FORCE_DEPENDS:
+              args->force_depends = 1;
+              break;
+         case ARGS_OPT_FORCE_OVERWRITE:
+              args->force_overwrite = 1;
+              break;
+         case ARGS_OPT_FORCE_DOWNGRADE:
+              args->force_downgrade = 1;
+              break;
+         case ARGS_OPT_FORCE_REINSTALL:
+              args->force_reinstall = 1;
+              break;
+         case ARGS_OPT_FORCE_REMOVAL_OF_ESSENTIAL_PACKAGES:
+              args->force_removal_of_essential_packages = 1;
+              break;
+         case ARGS_OPT_FORCE_REMOVAL_OF_DEPENDENT_PACKAGES:
+              args->force_removal_of_dependent_packages = 1;
+              break;
+         case ARGS_OPT_FORCE_SPACE:
+              args->force_space = 1;
+              break;
+         case ARGS_OPT_VERBOSE_WGET:
+              args->verbose_wget = 1;
+              break;
+         case ARGS_OPT_MULTIPLE_PROVIDERS:
+              args->multiple_providers = 1;
+              break;
+         case ARGS_OPT_NODEPS:
+              args->nodeps = 1;
+              break;
+         case ARGS_OPT_NOACTION:
+              args->noaction = 1;
+              break;
+         case ':':
+              parse_err++;
+              break;
+         case '?':
+              parse_err++;
+              break;
+         default:
+              printf("Confusion: getopt_long returned %d\n", c);
+         }
+     }
+    
+     if (parse_err) {
+         return -parse_err;
+     } else {
+         return optind;
+     }
+}
+
+void args_usage(char *complaint)
+{
+     if (complaint) {
+         fprintf(stderr, "opkg: %s\n", complaint);
+     }
+     print_version();
+     fprintf(stderr, "usage: opkg [options...] sub-command [arguments...]\n");
+     fprintf(stderr, "where sub-command is one of:\n");
+    
+     fprintf(stderr, "\nPackage Manipulation:\n");
+     fprintf(stderr, "\tupdate                 Update list of available packages\n");
+     fprintf(stderr, "\tupgrade                        Upgrade all installed packages to latest version\n");
+     fprintf(stderr, "\tinstall <pkg>          Download and install <pkg> (and dependencies)\n");
+     fprintf(stderr, "\tinstall <file.ipk>     Install package <file.ipk>\n");
+     fprintf(stderr, "\tconfigure [<pkg>]      Configure unpacked packages\n");
+     fprintf(stderr, "\tremove <pkg|regexp>    Remove package <pkg|packages following regexp>\n");
+     fprintf(stderr, "\tflag <flag> <pkg> ...  Flag package(s) <pkg>\n");
+     fprintf(stderr, "\t <flag>=hold|noprune|user|ok|installed|unpacked (one per invocation)   \n");
+    
+     fprintf(stderr, "\nInformational Commands:\n");
+     fprintf(stderr, "\tlist                   List available packages and descriptions\n");
+     fprintf(stderr, "\tlist_installed         List all and only the installed packages and description \n");
+     fprintf(stderr, "\tfiles <pkg>            List all files belonging to <pkg>\n");
+     fprintf(stderr, "\tsearch <file|regexp>           Search for a package providing <file>\n");
+#ifndef OPKG_LIB
+     fprintf(stderr, "\tinfo [pkg|regexp [<field>]]    Display all/some info fields for <pkg> or all\n");
+     fprintf(stderr, "\tstatus [pkg|regexp [<field>]]  Display all/some status fields for <pkg> or all\n");
+#else
+     fprintf(stderr, "\tinfo [pkg|regexp]              Display all info for <pkg>\n");
+     fprintf(stderr, "\tstatus [pkg|regexp]            Display all status for <pkg>\n");
+#endif
+     fprintf(stderr, "\tdownload <pkg>         Download <pkg> to current directory.\n");
+     fprintf(stderr, "\tcompare_versions <v1> <op> <v2>\n");
+     fprintf(stderr, "\t                          compare versions using <= < > >= = << >>\n");
+     fprintf(stderr, "\tprint_architecture      prints the architecture.\n");
+     fprintf(stderr, "\tprint_installation_architecture\n");
+     fprintf(stderr, "\twhatdepends [-A] [pkgname|pat]+\n");
+     fprintf(stderr, "\twhatdependsrec [-A] [pkgname|pat]+\n");
+     fprintf(stderr, "\twhatprovides [-A] [pkgname|pat]+\n");
+     fprintf(stderr, "\twhatconflicts [-A] [pkgname|pat]+\n");
+     fprintf(stderr, "\twhatreplaces [-A] [pkgname|pat]+\n");
+     fprintf(stderr, "\t                        prints the installation architecture.\n");    
+     fprintf(stderr, "\nOptions:\n");
+     fprintf(stderr, "\t-A                      Query all packages with whatdepends, whatprovides, whatreplaces, whatconflicts\n"); 
+     fprintf(stderr, "\t-V <level>               Set verbosity level to <level>. If no value is\n");
+     fprintf(stderr, "\t--verbosity <level>      provided increase verbosity by one. Verbosity levels:\n");
+     fprintf(stderr, "\t                         0 errors only\n");
+     fprintf(stderr, "\t                         1 normal messages (default)\n");
+     fprintf(stderr, "\t                         2 informative messages\n");
+     fprintf(stderr, "\t                         3 debug output\n");
+     fprintf(stderr, "\t-f <conf_file>         Use <conf_file> as the opkg configuration file\n");
+     fprintf(stderr, "\t-conf <conf_file>      Default configuration file location\n");
+     fprintf(stderr, "                         is %s/%s\n", ARGS_DEFAULT_CONF_FILE_DIR, ARGS_DEFAULT_CONF_FILE_NAME);
+     fprintf(stderr, "\t-d <dest_name>         Use <dest_name> as the the root directory for\n");
+     fprintf(stderr, "\t-dest <dest_name>      package installation, removal, upgrading.\n");
+     fprintf(stderr, "                         <dest_name> should be a defined dest name from\n");
+     fprintf(stderr, "                         the configuration file, (but can also be a\n");
+     fprintf(stderr, "                         directory name in a pinch).\n");
+     fprintf(stderr, "\t-o <offline_root>      Use <offline_root> as the root directory for\n");
+     fprintf(stderr, "\t-offline <offline_root>        offline installation of packages.\n");
+     fprintf(stderr, "\t-verbose_wget          more wget messages\n");
+    
+     fprintf(stderr, "\tForce Options (use when opkg is too smart for its own good):\n");
+     fprintf(stderr, "\t-force-depends         Make dependency checks warnings instead of errors\n");
+     fprintf(stderr, "\t                               Install/remove package in spite of failed dependences\n");
+     fprintf(stderr, "\t-force-defaults                Use default options for questions asked by opkg.\n");
+     fprintf(stderr, "                         (no prompts). Note that this will not prevent\n");
+     fprintf(stderr, "                         package installation scripts from prompting.\n");
+     fprintf(stderr, "\t-force-reinstall       Allow opkg to reinstall a package.\n");
+     fprintf(stderr, "\t-force-overwrite       Allow opkg to overwrite files from another package during an install.\n");
+     fprintf(stderr, "\t-force-downgrade       Allow opkg to downgrade packages.\n");
+     fprintf(stderr, "\t-force_space            Install even if there does not seem to be enough space.\n");
+     fprintf(stderr, "\t-noaction               No action -- test only\n");
+     fprintf(stderr, "\t-nodeps                 Do not follow dependences\n");
+     fprintf(stderr, "\t-force-removal-of-dependent-packages\n");
+     fprintf(stderr, "\t-recursive             Allow opkg to remove package and all that depend on it.\n");
+     fprintf(stderr, "\t-test                   No action -- test only\n");
+     fprintf(stderr, "\t-t                     Specify tmp-dir.\n");
+     fprintf(stderr, "\t--tmp-dir              Specify tmp-dir.\n");
+     fprintf(stderr, "\n");
+     fprintf(stderr, "\tregexp could be something like 'pkgname*' '*file*' or similar\n");
+     fprintf(stderr, "\teg: opkg info 'libstd*'  or opkg search '*libop*' or opkg remove 'libncur*'\n");
+     /* -force-removal-of-essential-packages   Let opkg remove essential packages. 
+       Using this option is almost guaranteed to break your system, hence this option
+       is not even advertised in the usage statement. */
+     exit(1);
+}
+
+static void print_version(void)
+{
+     fprintf(stderr, "opkg version %s\n", VERSION);
+}
diff --git a/libopkg/args.h b/libopkg/args.h
new file mode 100644 (file)
index 0000000..a470778
--- /dev/null
@@ -0,0 +1,72 @@
+/* args.h - parse command-line args
+
+  Carl D. Worth
+
+  Copyright 2001 University of Southern California
+  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, 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 General Public License for more details.
+*/
+
+#ifndef ARGS_H
+#define ARGS_H
+
+struct args
+{
+    char *conf_file;
+    char *dest;
+    char *tmp_dir;
+    int force_defaults;
+    int force_depends;
+    int force_overwrite;
+    int force_downgrade;
+    int force_reinstall;
+    int force_removal_of_essential_packages;
+    int force_removal_of_dependent_packages;
+    int force_space;
+    int noaction;
+    int nodeps;
+    int multiple_providers;
+    int query_all;
+    int verbose_wget;
+    int verbosity;
+    int nocheckfordirorfile;
+    int noreadfeedsfile;
+    char *offline_root;
+    char *offline_root_pre_script_cmd;
+    char *offline_root_post_script_cmd;
+};
+typedef struct args args_t;
+
+#define ARGS_DEFAULT_CONF_FILE_DIR "/etc"
+#define ARGS_DEFAULT_CONF_FILE_NAME "opkg.conf"
+#define ARGS_DEFAULT_DEST NULL
+#define ARGS_DEFAULT_FORCE_DEFAULTS 0
+#define ARGS_DEFAULT_FORCE_DEPENDS 0
+#define ARGS_DEFAULT_FORCE_OVERWRITE 0 
+#define ARGS_DEFAULT_FORCE_DOWNGRADE 0 
+#define ARGS_DEFAULT_FORCE_REINSTALL 0
+#define ARGS_DEFAULT_FORCE_REMOVAL_OF_ESSENTIAL_PACKAGES 0
+#define ARGS_DEFAULT_FORCE_REMOVAL_OF_DEPENDENT_PACKAGES 0
+#define ARGS_DEFAULT_FORCE_SPACE 0
+#define ARGS_DEFAULT_OFFLINE_ROOT NULL
+#define ARGS_DEFAULT_OFFLINE_ROOT_PRE_SCRIPT_CMD NULL
+#define ARGS_DEFAULT_OFFLINE_ROOT_POST_SCRIPT_CMD NULL
+#define ARGS_DEFAULT_NOACTION 0
+#define ARGS_DEFAULT_NODEPS 0
+#define ARGS_DEFAULT_VERBOSE_WGET 0
+#define ARGS_DEFAULT_VERBOSITY 1
+
+int args_init(args_t *args);
+void args_deinit(args_t *args);
+int args_parse(args_t *args, int argc, char *argv[]);
+void args_usage(char *complaint);
+
+#endif
diff --git a/libopkg/conffile.c b/libopkg/conffile.c
new file mode 100644 (file)
index 0000000..5f41cc1
--- /dev/null
@@ -0,0 +1,64 @@
+/* conffile.c - the itsy package management system
+
+   Carl D. Worth
+
+   Copyright (C) 2001 University of Southern California
+
+   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, 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
+   General Public License for more details.
+*/
+
+#include <string.h>
+#include <stdlib.h>
+
+#include "opkg.h"
+#include "opkg_message.h"
+
+#include "conffile.h"
+#include "file_util.h"
+#include "sprintf_alloc.h"
+
+int conffile_init(conffile_t *conffile, const char *file_name, const char *md5sum)
+{
+    return nv_pair_init(conffile, file_name, md5sum);
+}
+
+void conffile_deinit(conffile_t *conffile)
+{
+    nv_pair_deinit(conffile);
+}
+
+int conffile_has_been_modified(opkg_conf_t *conf, conffile_t *conffile)
+{
+    char *md5sum;
+    char *filename = conffile->name;
+    char *root_filename;
+    int ret;
+
+    if (conffile->value == NULL) {
+        opkg_message(conf, OPKG_NOTICE, "%s: conffile %s has no md5sum\n", __FUNCTION__, conffile->name);
+        return 1;
+    }
+
+    root_filename = root_filename_alloc(conf, filename);
+
+    md5sum = file_md5sum_alloc(root_filename);
+
+    ret = strcmp(md5sum, conffile->value);
+    if (ret) {
+      opkg_message(conf, OPKG_NOTICE, "%s: conffile %s: \t\nold md5=%s \t\nnew md5=%s\n", __FUNCTION__,
+              conffile->name, md5sum, conffile->value);
+    }
+
+    free(root_filename);
+    free(md5sum);
+
+    return ret;
+}
diff --git a/libopkg/conffile.h b/libopkg/conffile.h
new file mode 100644 (file)
index 0000000..130d1d8
--- /dev/null
@@ -0,0 +1,30 @@
+/* conffile.h - the itsy package management system
+
+   Carl D. Worth
+
+   Copyright (C) 2001 University of Southern California
+
+   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, 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
+   General Public License for more details.
+*/
+
+#ifndef CONFFILE_H
+#define CONFFILE_H
+
+#include "nv_pair.h"
+
+typedef struct nv_pair conffile_t;
+
+int conffile_init(conffile_t *conffile, const char *file_name, const char *md5sum);
+void conffile_deinit(conffile_t *conffile);
+int conffile_has_been_modified(struct opkg_conf *conf, conffile_t *conffile);
+
+#endif
+
diff --git a/libopkg/conffile_list.c b/libopkg/conffile_list.c
new file mode 100644 (file)
index 0000000..27d48d5
--- /dev/null
@@ -0,0 +1,47 @@
+/* conffile_list.c - the itsy package management system
+
+   Carl D. Worth
+
+   Copyright (C) 2001 University of Southern California
+
+   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, 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
+   General Public License for more details.
+*/
+
+#include "opkg.h"
+
+#include "conffile_list.h"
+
+int conffile_list_init(conffile_list_t *list)
+{
+    return nv_pair_list_init(list);
+}
+
+void conffile_list_deinit(conffile_list_t *list)
+{
+    nv_pair_list_deinit(list);
+}
+
+conffile_t *conffile_list_append(conffile_list_t *list, const char *file_name,
+                        const char *md5sum)
+{
+    return nv_pair_list_append(list, file_name, md5sum);
+}
+
+int conffile_list_push(conffile_list_t *list, conffile_t *data)
+{
+    return nv_pair_list_push(list, data);
+}
+
+conffile_list_elt_t *conffile_list_pop(conffile_list_t *list)
+{
+    return nv_pair_list_pop(list);
+}
+
diff --git a/libopkg/conffile_list.h b/libopkg/conffile_list.h
new file mode 100644 (file)
index 0000000..a5daac9
--- /dev/null
@@ -0,0 +1,36 @@
+/* conffile_list.h - the itsy package management system
+
+   Carl D. Worth
+
+   Copyright (C) 2001 University of Southern California
+
+   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, 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
+   General Public License for more details.
+*/
+
+#ifndef CONFFILE_LIST_H
+#define CONFFILE_LIST_H
+
+#include "conffile.h"
+#include "nv_pair_list.h"
+
+typedef struct nv_pair_list_elt conffile_list_elt_t;
+typedef struct nv_pair_list conffile_list_t;
+
+int conffile_list_init(conffile_list_t *list);
+void conffile_list_deinit(conffile_list_t *list);
+
+conffile_t *conffile_list_append(conffile_list_t *list, const char *name,
+                              const char *root_dir);
+int conffile_list_push(conffile_list_t *list, conffile_t *data);
+conffile_list_elt_t *conffile_list_pop(conffile_list_t *list);
+
+#endif
+
diff --git a/libopkg/file_util.c b/libopkg/file_util.c
new file mode 100644 (file)
index 0000000..da8a1cd
--- /dev/null
@@ -0,0 +1,177 @@
+/* file_util.c - convenience routines for common stat operations
+
+   Carl D. Worth
+
+   Copyright (C) 2001 University of Southern California
+
+   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, 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
+   General Public License for more details.
+*/
+
+#include "opkg.h"
+#include <sys/types.h>
+#include <sys/stat.h>
+
+#include "sprintf_alloc.h"
+#include "file_util.h"
+#include "md5.h"
+#include "libbb/libbb.h"
+#undef strlen
+
+int file_exists(const char *file_name)
+{
+    int err;
+    struct stat stat_buf;
+
+    err = stat(file_name, &stat_buf);
+    if (err == 0) {
+       return 1;
+    } else {
+       return 0;
+    }
+}
+
+int file_is_dir(const char *file_name)
+{
+    int err;
+    struct stat stat_buf;
+
+    err = stat(file_name, &stat_buf);
+    if (err) {
+       return 0;
+    }
+
+    return S_ISDIR(stat_buf.st_mode);
+}
+
+/* read a single line from a file, stopping at a newline or EOF.
+   If a newline is read, it will appear in the resulting string.
+   Return value is a malloc'ed char * which should be freed at
+   some point by the caller.
+
+   Return value is NULL if the file is at EOF when called.
+*/
+#define FILE_READ_LINE_BUF_SIZE 1024
+char *file_read_line_alloc(FILE *file)
+{
+    char buf[FILE_READ_LINE_BUF_SIZE];
+    int buf_len;
+    char *line = NULL;
+    int line_size = 0;
+
+    memset(buf, 0, FILE_READ_LINE_BUF_SIZE);
+    while (fgets(buf, FILE_READ_LINE_BUF_SIZE, file)) {
+       buf_len = strlen(buf);
+       if (line) {
+           line_size += buf_len;
+           line = realloc(line, line_size);
+           if (line == NULL) {
+               fprintf(stderr, "%s: out of memory\n", __FUNCTION__);
+               break;
+           }
+           strcat(line, buf);
+       } else {
+           line_size = buf_len + 1;
+           line = strdup(buf);
+       }
+       if (buf[buf_len - 1] == '\n') {
+           break;
+       }
+    }
+
+    return line;
+}
+
+int file_move(const char *src, const char *dest)
+{
+    int err;
+
+    err = rename(src, dest);
+
+    if (err && errno == EXDEV) {
+       err = file_copy(src, dest);
+       unlink(src);
+    } else if (err) {
+       fprintf(stderr, "%s: ERROR: failed to rename %s to %s: %s\n",
+               __FUNCTION__, src, dest, strerror(errno));
+    }
+
+    return err;
+}
+
+/* I put these here to keep libbb dependencies from creeping all over
+   the opkg code */
+int file_copy(const char *src, const char *dest)
+{
+    int err;
+
+    err = copy_file(src, dest, FILEUTILS_FORCE | FILEUTILS_PRESERVE_STATUS);
+    if (err) {
+       fprintf(stderr, "%s: ERROR: failed to copy %s to %s\n",
+               __FUNCTION__, src, dest);
+    }
+
+    return err;
+}
+
+int file_mkdir_hier(const char *path, long mode)
+{
+    return make_directory(path, mode, FILEUTILS_RECUR);
+}
+
+char *file_md5sum_alloc(const char *file_name)
+{
+    static const int md5sum_bin_len = 16;
+    static const int md5sum_hex_len = 32;
+
+    static const unsigned char bin2hex[16] = {
+       '0', '1', '2', '3',
+       '4', '5', '6', '7',
+       '8', '9', 'a', 'b',
+       'c', 'd', 'e', 'f'
+    };
+
+    int i, err;
+    FILE *file;
+    unsigned char *md5sum_hex;
+    unsigned char md5sum_bin[md5sum_bin_len];
+
+    md5sum_hex = malloc(md5sum_hex_len + 1);
+    if (md5sum_hex == NULL) {
+       fprintf(stderr, "%s: out of memory\n", __FUNCTION__);
+       return strdup("");
+    }
+
+    file = fopen(file_name, "r");
+    if (file == NULL) {
+       fprintf(stderr, "%s: Failed to open file %s: %s\n",
+               __FUNCTION__, file_name, strerror(errno));
+       return strdup("");
+    }
+
+    err = md5_stream(file, md5sum_bin);
+    if (err) {
+       fprintf(stderr, "%s: ERROR computing md5sum for %s: %s\n",
+               __FUNCTION__, file_name, strerror(err));
+       return strdup("");
+    }
+
+    fclose(file);
+
+    for (i=0; i < md5sum_bin_len; i++) {
+       md5sum_hex[i*2] = bin2hex[md5sum_bin[i] >> 4];
+       md5sum_hex[i*2+1] = bin2hex[md5sum_bin[i] & 0xf];
+    }
+    
+    md5sum_hex[md5sum_hex_len] = '\0';
+    
+    return md5sum_hex;
+}
+
diff --git a/libopkg/file_util.h b/libopkg/file_util.h
new file mode 100644 (file)
index 0000000..bcfb3cb
--- /dev/null
@@ -0,0 +1,29 @@
+/* file_util.h - convenience routines for common file operations
+
+   Carl D. Worth
+
+   Copyright (C) 2001 University of Southern California
+
+   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, 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
+   General Public License for more details.
+*/
+
+#ifndef FILE_UTIL_H
+#define FILE_UTIL_H
+
+int file_exists(const char *file_name);
+int file_is_dir(const char *file_name);
+char *file_read_line_alloc(FILE *file);
+int file_move(const char *src, const char *dest);
+int file_copy(const char *src, const char *dest);
+int file_mkdir_hier(const char *path, long mode);
+char *file_md5sum_alloc(const char *file_name);
+
+#endif
diff --git a/libopkg/hash_table.c b/libopkg/hash_table.c
new file mode 100644 (file)
index 0000000..41877c2
--- /dev/null
@@ -0,0 +1,155 @@
+/* hash.c - hash tables for opkg
+
+   Steven M. Ayer, Jamey Hicks
+   
+   Copyright (C) 2002 Compaq Computer Corporation
+
+   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, 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
+   General Public License for more details.
+*/
+
+#include <errno.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include "hash_table.h"
+#include "opkg_message.h"
+
+
+static int hash_index(hash_table_t *hash, const char *pkg_name);
+static int rotating(const char *key, int len, int prime);
+
+static int hash_index(hash_table_t *hash, const char *pkg_name)
+{
+    return rotating(pkg_name, strlen(pkg_name), hash->n_entries);
+}
+  
+static int rotating(const char *key, int len, int prime)
+{
+    unsigned int hash, i;
+    for (hash=len, i=0; i<len; ++i)
+       hash = (hash<<4)^(hash>>28)^key[i];
+    return (hash % prime);
+}
+
+
+/*
+ * this is an open table keyed by strings
+ */
+int hash_table_init(const char *name, hash_table_t *hash, int len)
+{
+    static int primes_table[] = {
+       379, 761, 983, 1423, 2711, 3361, 3931, 4679, 5519, 6701, 9587,
+       19471, 23143, 33961, 46499, 49727, 99529, 0
+    };
+    int *picker;
+
+    if (hash->entries != NULL) {
+       /* we have been here already */
+       return 0;
+    }
+
+    hash->name = name;
+    hash->entries = NULL;
+    hash->n_entries = 0;
+    hash->hash_entry_key = NULL;
+
+    picker = primes_table;
+    while(*picker && (*picker++ < len));
+    if(!*picker)
+       fprintf(stderr, "%s: primes table might not be big enough (! << %d)\n", __FUNCTION__, len);
+    --picker;
+
+    hash->n_entries = *picker;
+    hash->entries = (hash_entry_t *)calloc(hash->n_entries, sizeof(hash_entry_t));
+    if (hash->entries == NULL) {
+       fprintf(stderr, "%s: Out of memory.\n", __FUNCTION__);
+       return ENOMEM;
+    }
+    return 0;
+}
+
+void hash_table_deinit(hash_table_t *hash)
+{
+    free(hash->entries);
+    hash->entries = NULL;
+    hash->n_entries = 0;
+}
+
+void *hash_table_get(hash_table_t *hash, const char *key)
+{
+  int ndx= hash_index(hash, key);
+  hash_entry_t *hash_entry = hash->entries + ndx;
+  while (hash_entry) 
+  {
+    if (hash_entry->key) 
+    {
+      if (strcmp(key, hash_entry->key) == 0) {
+         // opkg_message(NULL, OPKG_DEBUG, "Function: %s. Key found for '%s' \n", __FUNCTION__, key);
+        return hash_entry->data;
+      }
+    }
+    hash_entry = hash_entry->next;
+  }
+  return NULL;
+}
+
+int hash_table_insert(hash_table_t *hash, const char *key, void *value)
+{
+     int ndx= hash_index(hash, key);
+     hash_entry_t *hash_entry = hash->entries + ndx;
+     if (0) opkg_message(NULL, OPKG_DEBUG2, "Function: %s. Inserting in hash for '%s' \n", __FUNCTION__, key);
+     if (hash_entry->key) {
+         if (strcmp(hash_entry->key, key) == 0) {
+              /* alread in table, update the value */
+               if (0) opkg_message(NULL, OPKG_DEBUG2, "Function: %s. Value already in hash for '%s' \n", __FUNCTION__, key);
+              hash_entry->data = value;
+              return 0;
+         } else {
+              /* 
+               * if this is a collision, we have to go to the end of the ll,
+               * then add a new entry
+               * before we can hook up the value
+               */
+               if (0) opkg_message(NULL, OPKG_DEBUG2, "Function: %s. Value already in hash by collision for '%s' \n", __FUNCTION__, key);
+              while (hash_entry->next)
+                   hash_entry = hash_entry->next;
+              hash_entry->next = (hash_entry_t *)malloc(sizeof(hash_entry_t));
+              if (!hash_entry->next) {
+                   return -ENOMEM;
+              }
+              hash_entry = hash_entry->next;
+              hash_entry->next = NULL;
+         }
+     }
+     hash->n_elements++;
+     hash_entry->key = strdup(key);
+     hash_entry->data = value;
+
+     return 0;
+}
+
+
+void hash_table_foreach(hash_table_t *hash, void (*f)(const char *key, void *entry, void *data), void *data)
+{ 
+    int i;
+    if (!hash || !f)
+       return;
+
+    for (i = 0; i < hash->n_entries; i++) {
+       hash_entry_t *hash_entry = (hash->entries + i);
+       do {
+           if(hash_entry->key) {
+               f(hash_entry->key, hash_entry->data, data);
+           }
+       } while((hash_entry = hash_entry->next));
+    }
+}
+
diff --git a/libopkg/hash_table.h b/libopkg/hash_table.h
new file mode 100644 (file)
index 0000000..388a966
--- /dev/null
@@ -0,0 +1,44 @@
+/* hash.h - hash tables for opkg
+
+   Steven M. Ayer, Jamey Hicks
+   
+   Copyright (C) 2002 Compaq Computer Corporation
+
+   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, 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
+   General Public License for more details.
+*/
+
+#ifndef _HASH_TABLE_H_
+#define _HASH_TABLE_H_
+
+typedef struct hash_entry hash_entry_t;
+typedef struct hash_table hash_table_t;
+
+struct hash_entry {
+  const char * key;
+  void * data;
+  struct hash_entry * next;
+};
+
+struct hash_table {
+  const char *name; 
+  hash_entry_t * entries;  
+  int n_entries; /* number of buckets */
+  int n_elements;
+  const char * (*hash_entry_key)(void * data);
+};
+
+int hash_table_init(const char *name, hash_table_t *hash, int len);
+void hash_table_deinit(hash_table_t *hash);
+void *hash_table_get(hash_table_t *hash, const char *key);
+int hash_table_insert(hash_table_t *hash, const char *key, void *value);
+void hash_table_foreach(hash_table_t *hash, void (*f)(const char *key, void *entry, void *data), void *data);
+
+#endif /* _HASH_TABLE_H_ */
diff --git a/libopkg/includes.h b/libopkg/includes.h
new file mode 100644 (file)
index 0000000..5a67001
--- /dev/null
@@ -0,0 +1,53 @@
+#ifndef INCLUDES_H
+#define INCLUDES_H
+
+#include <stdio.h>
+
+#if STDC_HEADERS
+# include <stdlib.h>
+# include <stdarg.h>
+# include <stddef.h>
+# include <ctype.h>
+# include <errno.h>
+#else
+# if HAVE_STDLIB_H
+#  include <stdlib.h>
+# endif
+#endif
+
+#if HAVE_REGEX_H
+# include <regex.h>
+#endif
+
+#if HAVE_STRING_H
+# if !STDC_HEADERS && HAVE_MEMORY_H
+#  include <memory.h>
+# endif
+/* XXX: What's the right way to pick up GNU's strndup declaration? */
+# if __GNUC__
+#   define __USE_GNU 1
+# endif
+# include <string.h>
+# undef __USE_GNU
+#endif
+
+#if HAVE_STRINGS_H
+# include <strings.h>
+#endif
+
+#if HAVE_SYS_STAT_H
+# include <sys/stat.h>
+#endif
+
+#if HAVE_SYS_WAIT_H
+# include <sys/wait.h>
+#endif
+
+#if HAVE_UNISTD_H
+# include <sys/types.h>
+# include <unistd.h>
+#endif
+
+// #include "replace/replace.h"
+
+#endif
diff --git a/libopkg/libopkg.c b/libopkg/libopkg.c
new file mode 100644 (file)
index 0000000..c57ad0a
--- /dev/null
@@ -0,0 +1,527 @@
+/* opkglib.c - the itsy package management system
+
+   Florina Boor
+
+   Copyright (C) 2003 kernel concepts
+
+   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, 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
+   General Public License for more details.
+*/
+
+#ifdef OPKG_LIB
+
+#include "opkg.h"
+#include "includes.h"
+#include "libopkg.h"
+
+#include "args.h"
+#include "opkg_conf.h"
+#include "opkg_cmd.h"
+#include "file_util.h"
+
+
+
+opkg_message_callback opkg_cb_message = NULL;
+opkg_response_callback opkg_cb_response = NULL;
+opkg_status_callback opkg_cb_status = NULL;
+opkg_list_callback opkg_cb_list = NULL;
+
+
+int
+opkg_init (opkg_message_callback mcall, 
+           opkg_response_callback rcall,
+           args_t * args)
+{
+       opkg_cb_message = mcall;
+       opkg_cb_response = rcall;
+
+       args_init (args);
+
+       return 0;
+}
+
+
+int
+opkg_deinit (args_t * args)
+{
+       args_deinit (args);
+       opkg_cb_message = NULL;
+       opkg_cb_response = NULL;
+
+       /* place other cleanup stuff here */
+
+       return 0;
+}
+
+
+int
+opkg_packages_list(args_t *args, 
+                   const char *packages, 
+                   opkg_list_callback cblist,
+                   void *userdata)
+{
+       opkg_cmd_t *cmd;
+       opkg_conf_t opkg_conf;
+       int err;
+
+       err = opkg_conf_init (&opkg_conf, args);
+       if (err)
+       {
+               return err;
+       }
+
+       opkg_cb_list = cblist;
+       /* we need to do this because of static declarations, 
+        * maybe a good idea to change */
+       cmd = opkg_cmd_find ("list");
+       if (packages)
+               err = opkg_cmd_exec (cmd, &opkg_conf, 1, &packages, userdata);
+       else
+               err = opkg_cmd_exec (cmd, &opkg_conf, 0, NULL, userdata);
+       opkg_cb_list = NULL;
+       opkg_conf_deinit (&opkg_conf);
+       return (err);
+}
+
+
+int
+opkg_packages_status(args_t *args,
+                     const char *packages,
+                     opkg_status_callback cbstatus,
+                     void *userdata)
+{
+       opkg_cmd_t *cmd;
+       opkg_conf_t opkg_conf;
+       int err;
+
+       err = opkg_conf_init (&opkg_conf, args);
+       if (err)
+       {
+               return err;
+       }
+
+       opkg_cb_status = cbstatus;
+
+       /* we need to do this because of static declarations,
+        * maybe a good idea to change */
+       cmd = opkg_cmd_find ("status");
+       if (packages)
+               err = opkg_cmd_exec (cmd, &opkg_conf, 1, &packages, userdata);
+       else
+               err = opkg_cmd_exec (cmd, &opkg_conf, 0, NULL, userdata);
+
+       opkg_cb_status = NULL;
+       opkg_conf_deinit (&opkg_conf);
+       return (err);
+}
+
+
+int
+opkg_packages_info(args_t *args,
+                   const char *packages,
+                   opkg_status_callback cbstatus,
+                   void *userdata)
+{
+       opkg_cmd_t *cmd;
+       opkg_conf_t opkg_conf;
+       int err;
+
+       err = opkg_conf_init (&opkg_conf, args);
+       if (err)
+       {
+               return err;
+       }
+
+       opkg_cb_status = cbstatus;
+
+       /* we need to do this because of static declarations,
+        * maybe a good idea to change */
+       cmd = opkg_cmd_find ("info");
+       if (packages)
+               err = opkg_cmd_exec (cmd, &opkg_conf, 1, &packages, userdata);
+       else
+               err = opkg_cmd_exec (cmd, &opkg_conf, 0, NULL, userdata);
+
+       opkg_cb_status = NULL;
+       opkg_conf_deinit (&opkg_conf);
+       return (err);
+}
+
+
+int
+opkg_packages_install (args_t * args, const char *name)
+{
+       opkg_cmd_t *cmd;
+       opkg_conf_t opkg_conf;
+       int err;
+
+       /* this error should be handled in application */
+       if (!name || !strlen (name))
+               return (-1);
+
+       err = opkg_conf_init (&opkg_conf, args);
+       if (err)
+       {
+               return err;
+       }
+
+       /* we need to do this because of static declarations,
+        * maybe a good idea to change */
+       cmd = opkg_cmd_find ("install");
+       err = opkg_cmd_exec (cmd, &opkg_conf, 1, &name, NULL);
+
+       opkg_conf_deinit(&opkg_conf);
+       return (err);
+}
+
+
+int
+opkg_packages_remove(args_t *args, const char *name, int purge)
+{
+       opkg_cmd_t *cmd;
+       opkg_conf_t opkg_conf;
+       int err;
+
+       /* this error should be handled in application */
+       if (!name || !strlen (name))
+               return (-1);
+
+       err = opkg_conf_init (&opkg_conf, args);
+       if (err)
+       {
+               return err;
+       }
+
+       /* we need to do this because of static declarations, 
+        * maybe a good idea to change */
+       if (purge)
+               cmd = opkg_cmd_find ("purge");
+       else
+               cmd = opkg_cmd_find ("remove");
+
+       err = opkg_cmd_exec (cmd, &opkg_conf, 1, &name, NULL);
+       
+       opkg_conf_deinit(&opkg_conf);
+       return (err);
+}
+
+
+int 
+opkg_lists_update(args_t *args)
+{
+       opkg_cmd_t *cmd;
+       opkg_conf_t opkg_conf;
+       int err;
+
+       err = opkg_conf_init (&opkg_conf, args);
+       if (err)
+       {
+               return err;
+       }
+
+       /* we need to do this because of static declarations, 
+        * maybe a good idea to change */
+       cmd = opkg_cmd_find ("update");
+
+       err = opkg_cmd_exec (cmd, &opkg_conf, 0, NULL, NULL);
+       
+       opkg_conf_deinit(&opkg_conf);
+       return (err);
+}
+
+
+int 
+opkg_packages_upgrade(args_t *args)
+{
+       opkg_cmd_t *cmd;
+       opkg_conf_t opkg_conf;
+       int err;
+
+       err = opkg_conf_init (&opkg_conf, args);
+       if (err)
+       {
+               return err;
+       }
+
+       /* we need to do this because of static declarations, 
+        * maybe a good idea to change */
+       cmd = opkg_cmd_find ("upgrade");
+
+       err = opkg_cmd_exec (cmd, &opkg_conf, 0, NULL, NULL);
+       
+       opkg_conf_deinit(&opkg_conf);
+       return (err);
+}
+
+
+int
+opkg_packages_download (args_t * args, const char *name)
+{
+       opkg_cmd_t *cmd;
+       opkg_conf_t opkg_conf;
+       int err;
+
+       /* this error should be handled in application */
+       if (!name || !strlen (name))
+               return (-1);
+
+       err = opkg_conf_init (&opkg_conf, args);
+       if (err)
+       {
+               return err;
+       }
+
+       /* we need to do this because of static declarations,
+        * maybe a good idea to change */
+       cmd = opkg_cmd_find ("download");
+       err = opkg_cmd_exec (cmd, &opkg_conf, 1, &name, NULL);
+
+       opkg_conf_deinit(&opkg_conf);
+       return (err);
+}
+
+
+int
+opkg_package_files(args_t *args, 
+                   const char *name, 
+                   opkg_list_callback cblist,
+                   void *userdata)
+{
+       opkg_cmd_t *cmd;
+       opkg_conf_t opkg_conf;
+       int err;
+
+       /* this error should be handled in application */
+       if (!name || !strlen (name))
+               return (-1);
+
+       err = opkg_conf_init (&opkg_conf, args);
+       if (err)
+       {
+               return err;
+       }
+
+       opkg_cb_list = cblist;
+       
+       /* we need to do this because of static declarations, 
+        * maybe a good idea to change */
+       cmd = opkg_cmd_find ("files");
+
+       err = opkg_cmd_exec (cmd, &opkg_conf, 1, &name, userdata);
+       
+       opkg_cb_list = NULL;
+       opkg_conf_deinit(&opkg_conf);
+       return (err);
+}
+
+
+int 
+opkg_file_search(args_t *args, 
+                const char *file,
+                               opkg_list_callback cblist,
+                void *userdata)
+{
+       opkg_cmd_t *cmd;
+       opkg_conf_t opkg_conf;
+       int err;
+       
+       /* this error should be handled in application */
+       if (!file || !strlen (file))
+               return (-1);
+
+       err = opkg_conf_init (&opkg_conf, args);
+       if (err)
+       {
+               return err;
+       }
+
+       opkg_cb_list = cblist;
+
+       /* we need to do this because of static declarations, 
+        * maybe a good idea to change */
+       cmd = opkg_cmd_find ("search");
+       err = opkg_cmd_exec (cmd, &opkg_conf, 1, &file, userdata);
+       
+       opkg_cb_list = NULL;
+       opkg_conf_deinit(&opkg_conf);
+       return(err);
+}
+
+
+int 
+opkg_file_what(args_t *args, const char *file, const char* command)
+{
+       opkg_cmd_t *cmd;
+       opkg_conf_t opkg_conf;
+       int err;
+       
+       /* this error should be handled in application */
+       if (!file || !strlen (file))
+               return (-1);
+
+       err = opkg_conf_init (&opkg_conf, args);
+       if (err)
+       {
+               return err;
+       }
+
+       /* we need to do this because of static declarations, 
+        * maybe a good idea to change */
+       cmd = opkg_cmd_find (command);
+       err = opkg_cmd_exec (cmd, &opkg_conf, 1, &file, NULL);
+       
+       opkg_conf_deinit(&opkg_conf);
+       return(err);
+}
+
+#define opkg_package_whatdepends(args,file) opkg_file_what(args,file,"whatdepends")
+#define opkg_package_whatrecommends(args, file) opkg_file_what(args,file,"whatrecommends")
+#define opkg_package_whatprovides(args, file) opkg_file_what(args,file,"whatprovides")
+#define opkg_package_whatconflicts(args, file) opkg_file_what(args,file,"whatconflicts")
+#define opkg_package_whatreplaces(args, file) opkg_file_what(args,file,"whatreplaces")
+
+
+int default_opkg_message_callback(opkg_conf_t *conf, message_level_t level, 
+                                 char *msg)
+{
+     if (conf && (conf->verbosity < level)) {
+         return 0;
+     } else {
+#ifdef OPKG_LIB
+          if ( level == OPKG_ERROR ){
+             push_error_list(&error_list, msg); 
+//          printf(msg);
+          } else
+#endif
+            printf(msg);
+     }
+     return 0;
+}
+
+int default_opkg_list_callback(char *name, char *desc, char *version, 
+                              pkg_state_status_t status, void *userdata)
+{
+     if (desc)
+         printf("%s - %s - %s\n", name, version, desc);
+     else
+         printf("%s - %s\n", name, version);
+     return 0;
+}
+
+int default_opkg_files_callback(char *name, char *desc, char *version,
+                   pkg_state_status_t status, void *userdata)
+{
+     if (desc)
+         printf("%s\n", desc);
+     return 0;
+}
+
+int default_opkg_status_callback(char *name, int istatus, char *desc,
+                                void *userdata)
+{
+     printf("%s\n", desc);
+     return 0;
+}
+
+char* default_opkg_response_callback(char *question)
+{
+     char *response = NULL;
+     printf(question);
+     fflush(stdout);
+     do {
+         response = (char *)file_read_line_alloc(stdin);
+     } while (response == NULL);
+     return response;
+}
+
+/* This is used for backward compatibility */
+int
+opkg_op (int argc, char *argv[])
+{
+       int err, optind;
+       args_t args;
+       char *cmd_name;
+       opkg_cmd_t *cmd;
+       opkg_conf_t opkg_conf;
+
+       args_init (&args);
+
+       optind = args_parse (&args, argc, argv);
+       if (optind == argc || optind < 0)
+       {
+               args_usage ("opkg must have one sub-command argument");
+       }
+
+       cmd_name = argv[optind++];
+/* Pigi: added a flag to disable the checking of structures if the command does not need to 
+         read anything from there.
+*/
+        if ( !strcmp(cmd_name,"print-architecture") ||
+             !strcmp(cmd_name,"print_architecture") ||
+             !strcmp(cmd_name,"print-installation-architecture") ||
+             !strcmp(cmd_name,"print_installation_architecture") )
+           args.nocheckfordirorfile = 1;
+
+/* Pigi: added a flag to disable the reading of feed files  if the command does not need to 
+         read anything from there.
+*/
+        if ( !strcmp(cmd_name,"flag") ||
+             !strcmp(cmd_name,"configure") ||
+             !strcmp(cmd_name,"remove") ||
+             !strcmp(cmd_name,"files") ||
+             !strcmp(cmd_name,"search") ||
+             !strcmp(cmd_name,"compare_versions") ||
+             !strcmp(cmd_name,"compare-versions") ||
+             !strcmp(cmd_name,"list_installed") ||
+             !strcmp(cmd_name,"list-installed") ||
+             !strcmp(cmd_name,"status") )
+           args.noreadfeedsfile = 1;
+
+
+       err = opkg_conf_init (&opkg_conf, &args);
+       if (err)
+       {
+               return err;
+       }
+
+       args_deinit (&args);
+
+       opkg_cb_message = default_opkg_message_callback;
+       opkg_cb_response = default_opkg_response_callback;
+       opkg_cb_status = default_opkg_status_callback;
+       if ( strcmp(cmd_name, "files")==0)
+            opkg_cb_list = default_opkg_files_callback;
+       else
+            opkg_cb_list = default_opkg_list_callback;
+
+       cmd = opkg_cmd_find (cmd_name);
+       if (cmd == NULL)
+       {
+               fprintf (stderr, "%s: unknown sub-command %s\n", argv[0],
+                        cmd_name);
+               args_usage (NULL);
+       }
+
+       if (cmd->requires_args && optind == argc)
+       {
+               fprintf (stderr,
+                        "%s: the ``%s'' command requires at least one argument\n",
+                        __FUNCTION__, cmd_name);
+               args_usage (NULL);
+       }
+
+       err = opkg_cmd_exec (cmd, &opkg_conf, argc - optind, (const char **) (argv + optind), NULL);
+
+       opkg_conf_deinit (&opkg_conf);
+
+       return err;
+}
+
+#endif /* OPKG_LIB */
diff --git a/libopkg/libopkg.h b/libopkg/libopkg.h
new file mode 100644 (file)
index 0000000..3430e1c
--- /dev/null
@@ -0,0 +1,94 @@
+/* opkglib.h - the itsy package management system
+
+   Florian Boor <florian.boor@kernelconcepts.de>
+
+   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, 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
+   General Public License for more details.
+*/
+
+#ifndef OPKGLIB_H
+#define OPKGLIB_H
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+
+#ifdef OPKG_LIB
+
+#include "opkg_conf.h"
+#include "opkg_message.h"
+#include "opkg_state.h"
+
+#include "args.h"
+#include "pkg.h"
+
+typedef int (*opkg_message_callback)(opkg_conf_t *conf, message_level_t level, 
+       char *msg);
+typedef int (*opkg_list_callback)(char *name, char *desc, char *version, 
+       pkg_state_status_t status, void *userdata);
+typedef int (*opkg_status_callback)(char *name, int istatus, char *desc,
+       void *userdata);
+typedef char* (*opkg_response_callback)(char *question);
+typedef void (*opkg_download_progress_callback)(int percent, char *url);
+typedef void (*opkg_state_changed_callback)(opkg_state_t state, const char *data);
+
+extern int opkg_op(int argc, char *argv[]); /* opkglib.c */
+extern int opkg_init (opkg_message_callback mcall, 
+                      opkg_response_callback rcall,
+                                         args_t * args);
+
+extern int opkg_deinit (args_t *args);
+extern int opkg_packages_list(args_t *args, 
+                              const char *packages, 
+                              opkg_list_callback cblist,
+                              void *userdata);
+extern int opkg_packages_status(args_t *args, 
+                                const char *packages, 
+                                opkg_status_callback cbstatus,
+                                                               void *userdata);
+extern int opkg_packages_info(args_t *args,
+                              const char *packages,
+                              opkg_status_callback cbstatus,
+                              void *userdata);
+extern int opkg_packages_install(args_t *args, const char *name);
+extern int opkg_packages_remove(args_t *args, const char *name, int purge);
+extern int opkg_lists_update(args_t *args);
+extern int opkg_packages_upgrade(args_t *args);
+extern int opkg_packages_download(args_t *args, const char *name);
+extern int opkg_package_files(args_t *args,
+                              const char *name,
+                                                         opkg_list_callback cblist,
+                                                         void *userdata);
+extern int opkg_file_search(args_t *args,
+                            const char *file,
+                                                       opkg_list_callback cblist,
+                                                       void *userdata);
+extern int opkg_package_whatdepends(args_t *args, const char *file);
+extern int opkg_package_whatrecommends(args_t *args, const char *file);
+extern int opkg_package_whatprovides(args_t *args, const char *file);
+extern int opkg_package_whatconflicts(args_t *args, const char *file);
+extern int opkg_package_whatreplaces(args_t *args, const char *file);
+
+extern opkg_message_callback opkg_cb_message; /* opkglib.c */
+extern opkg_response_callback opkg_cb_response;
+extern opkg_status_callback opkg_cb_status;
+extern opkg_list_callback opkg_cb_list;
+extern opkg_download_progress_callback opkg_cb_download_progress; /* opkg_download.c */
+extern opkg_state_changed_callback opkg_cb_state_changed; /* opkg_state.c */
+
+extern void push_error_list(struct errlist **errors,char * msg);
+extern void reverse_error_list(struct errlist **errors);
+extern void free_error_list();
+
+#endif
+
+
+#endif
diff --git a/libopkg/md5.c b/libopkg/md5.c
new file mode 100644 (file)
index 0000000..9cbc228
--- /dev/null
@@ -0,0 +1,658 @@
+/* md5.c - Compute MD5 checksum of files or strings according to the
+ *         definition of MD5 in RFC 1321 from April 1992.
+ * Copyright (C) 1995-1999 Free Software Foundation, Inc.
+ *
+ * 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, 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 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.
+ */
+
+/* Written by Ulrich Drepper <drepper@gnu.ai.mit.edu> */
+/* Hacked to work with BusyBox by Alfred M. Szmidt <ams@trillian.itslinux.org> */
+
+/* Sucked directly into opkg since the md5sum functions aren't in libbb
+   Dropped a few functions since opkg only needs md5_stream.
+   Got rid of evil, twisted defines of FALSE=1 and TRUE=0
+   6 March 2002 Carl Worth <cworth@east.isi.edu>
+*/
+
+/*
+ * June 29, 2001        Manuel Novoa III
+ *
+ * Added MD5SUM_SIZE_VS_SPEED configuration option.
+ *
+ * Current valid values, with data from my system for comparison, are:
+ *   (using uClibc and running on linux-2.4.4.tar.bz2)
+ *                     user times (sec)  text size (386)
+ *     0 (fastest)         1.1                6144
+ *     1                   1.4                5392
+ *     2                   3.0                5088
+ *     3 (smallest)        5.1                4912
+ */
+
+#define MD5SUM_SIZE_VS_SPEED 3
+
+/**********************************************************************/
+
+#include <stdio.h>
+#include <errno.h>
+#include <ctype.h>
+#include <getopt.h>
+#include <stdlib.h>
+#include <string.h>
+#include <endian.h>
+#include <sys/types.h>
+#if defined HAVE_LIMITS_H
+# include <limits.h>
+#endif
+
+#include "md5.h"
+
+//----------------------------------------------------------------------------
+//--------md5.c
+//----------------------------------------------------------------------------
+
+/* md5.c - Functions to compute MD5 message digest of files or memory blocks
+ *         according to the definition of MD5 in RFC 1321 from April 1992.
+ */
+
+/* Written by Ulrich Drepper <drepper@gnu.ai.mit.edu>, 1995.  */
+
+//----------------------------------------------------------------------------
+//--------md5.h
+//----------------------------------------------------------------------------
+
+/* md5.h - Declaration of functions and data types used for MD5 sum
+   computing library functions. */
+
+typedef u_int32_t md5_uint32;
+
+/* Structure to save state of computation between the single steps.  */
+struct md5_ctx
+{
+  md5_uint32 A;
+  md5_uint32 B;
+  md5_uint32 C;
+  md5_uint32 D;
+
+  md5_uint32 total[2];
+  md5_uint32 buflen;
+  char buffer[128];
+};
+
+/*
+ * The following three functions are build up the low level used in
+ * the functions `md5_stream' and `md5_buffer'.
+ */
+
+/* Initialize structure containing state of computation.
+   (RFC 1321, 3.3: Step 3)  */
+static void md5_init_ctx __P ((struct md5_ctx *ctx));
+
+/* Starting with the result of former calls of this function (or the
+   initialization function update the context for the next LEN bytes
+   starting at BUFFER.
+   It is necessary that LEN is a multiple of 64!!! */
+static void md5_process_block __P ((const void *buffer, size_t len,
+                                   struct md5_ctx *ctx));
+
+/* Starting with the result of former calls of this function (or the
+   initialization function update the context for the next LEN bytes
+   starting at BUFFER.
+   It is NOT required that LEN is a multiple of 64.  */
+static void md5_process_bytes __P ((const void *buffer, size_t len,
+                                   struct md5_ctx *ctx));
+
+/* Process the remaining bytes in the buffer and put result from CTX
+   in first 16 bytes following RESBUF.  The result is always in little
+   endian byte order, so that a byte-wise output yields to the wanted
+   ASCII representation of the message digest.
+
+   IMPORTANT: On some systems it is required that RESBUF is correctly
+   aligned for a 32 bits value.  */
+static void *md5_finish_ctx __P ((struct md5_ctx *ctx, void *resbuf));
+
+//----------------------------------------------------------------------------
+//--------end of md5.h
+//----------------------------------------------------------------------------
+
+/* Handle endian-ness */
+#if __BYTE_ORDER == __LITTLE_ENDIAN
+       #define SWAP(n) (n)
+#else
+       #define SWAP(n) ((n << 24) | ((n&65280)<<8) | ((n&16711680)>>8) | (n>>24))
+#endif
+
+
+
+#if MD5SUM_SIZE_VS_SPEED == 0
+/* This array contains the bytes used to pad the buffer to the next
+   64-byte boundary.  (RFC 1321, 3.1: Step 1)  */
+static const unsigned char fillbuf[64] = { 0x80, 0 /* , 0, 0, ...  */  };
+#endif
+
+/* Initialize structure containing state of computation.
+   (RFC 1321, 3.3: Step 3)  */
+void md5_init_ctx(struct md5_ctx *ctx)
+{
+  ctx->A = 0x67452301;
+  ctx->B = 0xefcdab89;
+  ctx->C = 0x98badcfe;
+  ctx->D = 0x10325476;
+
+  ctx->total[0] = ctx->total[1] = 0;
+  ctx->buflen = 0;
+}
+
+/* Process the remaining bytes in the internal buffer and the usual
+   prolog according to the standard and write the result to RESBUF.
+
+   IMPORTANT: On some systems it is required that RESBUF is correctly
+   aligned for a 32 bits value.  */
+static void *md5_finish_ctx(struct md5_ctx *ctx, void *resbuf)
+{
+  /* Take yet unprocessed bytes into account.  */
+  md5_uint32 bytes = ctx->buflen;
+  size_t pad;
+
+  /* Now count remaining bytes.  */
+  ctx->total[0] += bytes;
+  if (ctx->total[0] < bytes)
+    ++ctx->total[1];
+
+  pad = bytes >= 56 ? 64 + 56 - bytes : 56 - bytes;
+#if MD5SUM_SIZE_VS_SPEED > 0
+  memset(&ctx->buffer[bytes], 0, pad);
+  ctx->buffer[bytes] = 0x80;
+#else
+  memcpy(&ctx->buffer[bytes], fillbuf, pad);
+#endif
+
+  /* Put the 64-bit file length in *bits* at the end of the buffer.  */
+  *(md5_uint32 *) & ctx->buffer[bytes + pad] = SWAP(ctx->total[0] << 3);
+  *(md5_uint32 *) & ctx->buffer[bytes + pad + 4] =
+    SWAP( ((ctx->total[1] << 3) | (ctx->total[0] >> 29)) );
+
+  /* Process last bytes.  */
+  md5_process_block(ctx->buffer, bytes + pad + 8, ctx);
+
+/* Put result from CTX in first 16 bytes following RESBUF.  The result is
+   always in little endian byte order, so that a byte-wise output yields
+   to the wanted ASCII representation of the message digest.
+
+   IMPORTANT: On some systems it is required that RESBUF is correctly
+   aligned for a 32 bits value.  */
+  ((md5_uint32 *) resbuf)[0] = SWAP(ctx->A);
+  ((md5_uint32 *) resbuf)[1] = SWAP(ctx->B);
+  ((md5_uint32 *) resbuf)[2] = SWAP(ctx->C);
+  ((md5_uint32 *) resbuf)[3] = SWAP(ctx->D);
+
+  return resbuf;
+}
+
+/* Compute MD5 message digest for bytes read from STREAM.  The
+   resulting message digest number will be written into the 16 bytes
+   beginning at RESBLOCK.  */
+int md5_stream(FILE *stream, void *resblock)
+{
+  /* Important: BLOCKSIZE must be a multiple of 64.  */
+static const int BLOCKSIZE = 4096;
+  struct md5_ctx ctx;
+  char buffer[BLOCKSIZE + 72];
+  size_t sum;
+
+  /* Initialize the computation context.  */
+  md5_init_ctx(&ctx);
+
+  /* Iterate over full file contents.  */
+  while (1) {
+    /* We read the file in blocks of BLOCKSIZE bytes.  One call of the
+       computation function processes the whole buffer so that with the
+       next round of the loop another block can be read.  */
+    size_t n;
+    sum = 0;
+
+    /* Read block.  Take care for partial reads.  */
+    do {
+      n = fread(buffer + sum, 1, BLOCKSIZE - sum, stream);
+
+      sum += n;
+    }
+    while (sum < BLOCKSIZE && n != 0);
+    if (n == 0 && ferror(stream))
+      return 1;
+
+    /* If end of file is reached, end the loop.  */
+    if (n == 0)
+      break;
+
+    /* Process buffer with BLOCKSIZE bytes.  Note that
+       BLOCKSIZE % 64 == 0
+    */
+    md5_process_block(buffer, BLOCKSIZE, &ctx);
+  }
+
+  /* Add the last bytes if necessary.  */
+  if (sum > 0)
+    md5_process_bytes(buffer, sum, &ctx);
+
+  /* Construct result in desired memory.  */
+  md5_finish_ctx(&ctx, resblock);
+  return 0;
+}
+
+/* Compute MD5 message digest for LEN bytes beginning at BUFFER.  The
+   result is always in little endian byte order, so that a byte-wise
+   output yields to the wanted ASCII representation of the message
+   digest.  */
+void *md5_buffer(const char *buffer, size_t len, void *resblock)
+{
+  struct md5_ctx ctx;
+
+  /* Initialize the computation context.  */
+  md5_init_ctx(&ctx);
+
+  /* Process whole buffer but last len % 64 bytes.  */
+  md5_process_bytes(buffer, len, &ctx);
+
+  /* Put result in desired memory area.  */
+  return md5_finish_ctx(&ctx, resblock);
+}
+
+static void md5_process_bytes(const void *buffer, size_t len, struct md5_ctx *ctx)
+{
+  /* When we already have some bits in our internal buffer concatenate
+     both inputs first.  */
+  if (ctx->buflen != 0) {
+    size_t left_over = ctx->buflen;
+    size_t add = 128 - left_over > len ? len : 128 - left_over;
+
+    memcpy(&ctx->buffer[left_over], buffer, add);
+    ctx->buflen += add;
+
+    if (left_over + add > 64) {
+      md5_process_block(ctx->buffer, (left_over + add) & ~63, ctx);
+      /* The regions in the following copy operation cannot overlap.  */
+      memcpy(ctx->buffer, &ctx->buffer[(left_over + add) & ~63],
+            (left_over + add) & 63);
+      ctx->buflen = (left_over + add) & 63;
+    }
+
+    buffer = (const char *) buffer + add;
+    len -= add;
+  }
+
+  /* Process available complete blocks.  */
+  if (len > 64) {
+    md5_process_block(buffer, len & ~63, ctx);
+    buffer = (const char *) buffer + (len & ~63);
+    len &= 63;
+  }
+
+  /* Move remaining bytes in internal buffer.  */
+  if (len > 0) {
+    memcpy(ctx->buffer, buffer, len);
+    ctx->buflen = len;
+  }
+}
+
+/* These are the four functions used in the four steps of the MD5 algorithm
+   and defined in the RFC 1321.  The first function is a little bit optimized
+   (as found in Colin Plumbs public domain implementation).  */
+/* #define FF(b, c, d) ((b & c) | (~b & d)) */
+#define FF(b, c, d) (d ^ (b & (c ^ d)))
+#define FG(b, c, d) FF (d, b, c)
+#define FH(b, c, d) (b ^ c ^ d)
+#define FI(b, c, d) (c ^ (b | ~d))
+
+/* Process LEN bytes of BUFFER, accumulating context into CTX.
+   It is assumed that LEN % 64 == 0.  */
+static void md5_process_block(const void *buffer, size_t len, struct md5_ctx *ctx)
+{
+  md5_uint32 correct_words[16];
+  const md5_uint32 *words = buffer;
+  size_t nwords = len / sizeof(md5_uint32);
+  const md5_uint32 *endp = words + nwords;
+#if MD5SUM_SIZE_VS_SPEED > 0
+  static const md5_uint32 C_array[] = {
+      /* round 1 */
+      0xd76aa478, 0xe8c7b756, 0x242070db, 0xc1bdceee,
+      0xf57c0faf, 0x4787c62a, 0xa8304613, 0xfd469501,
+      0x698098d8, 0x8b44f7af, 0xffff5bb1, 0x895cd7be,
+      0x6b901122, 0xfd987193, 0xa679438e, 0x49b40821,
+      /* round 2 */
+      0xf61e2562, 0xc040b340, 0x265e5a51, 0xe9b6c7aa,
+      0xd62f105d, 0x2441453,  0xd8a1e681, 0xe7d3fbc8,
+      0x21e1cde6, 0xc33707d6, 0xf4d50d87, 0x455a14ed,
+      0xa9e3e905, 0xfcefa3f8, 0x676f02d9, 0x8d2a4c8a,
+      /* round 3 */
+      0xfffa3942, 0x8771f681, 0x6d9d6122, 0xfde5380c,
+      0xa4beea44, 0x4bdecfa9, 0xf6bb4b60, 0xbebfbc70,
+      0x289b7ec6, 0xeaa127fa, 0xd4ef3085, 0x4881d05,
+      0xd9d4d039, 0xe6db99e5, 0x1fa27cf8, 0xc4ac5665,
+      /* round 4 */
+      0xf4292244, 0x432aff97, 0xab9423a7, 0xfc93a039,
+      0x655b59c3, 0x8f0ccc92, 0xffeff47d, 0x85845dd1,
+      0x6fa87e4f, 0xfe2ce6e0, 0xa3014314, 0x4e0811a1,
+      0xf7537e82, 0xbd3af235, 0x2ad7d2bb, 0xeb86d391
+  };
+
+  static const char P_array[] = {
+#if MD5SUM_SIZE_VS_SPEED > 1
+      0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, /* 1 */
+#endif
+      1, 6, 11, 0, 5, 10, 15, 4, 9, 14, 3, 8, 13, 2, 7, 12, /* 2 */
+      5, 8, 11, 14, 1, 4, 7, 10, 13, 0, 3, 6, 9, 12, 15, 2, /* 3 */
+      0, 7, 14, 5, 12, 3, 10, 1, 8, 15, 6, 13, 4, 11, 2, 9  /* 4 */
+  };
+
+#if MD5SUM_SIZE_VS_SPEED > 1
+  static const char S_array[] = {
+      7, 12, 17, 22,
+      5, 9, 14, 20,
+      4, 11, 16, 23,
+      6, 10, 15, 21
+  };
+#endif
+#endif
+
+  md5_uint32 A = ctx->A;
+  md5_uint32 B = ctx->B;
+  md5_uint32 C = ctx->C;
+  md5_uint32 D = ctx->D;
+
+  /* First increment the byte count.  RFC 1321 specifies the possible
+     length of the file up to 2^64 bits.  Here we only compute the
+     number of bytes.  Do a double word increment.  */
+  ctx->total[0] += len;
+  if (ctx->total[0] < len)
+    ++ctx->total[1];
+
+  /* Process all bytes in the buffer with 64 bytes in each round of
+     the loop.  */
+  while (words < endp) {
+    md5_uint32 *cwp = correct_words;
+    md5_uint32 A_save = A;
+    md5_uint32 B_save = B;
+    md5_uint32 C_save = C;
+    md5_uint32 D_save = D;
+
+#if MD5SUM_SIZE_VS_SPEED > 1
+#define CYCLIC(w, s) (w = (w << s) | (w >> (32 - s)))
+
+    const md5_uint32 *pc;
+    const char *pp;
+    const char *ps;
+    int i;
+    md5_uint32 temp;
+
+    for ( i=0 ; i < 16 ; i++ ) {
+       cwp[i] = SWAP(words[i]);
+    }
+    words += 16;
+
+#if MD5SUM_SIZE_VS_SPEED > 2
+    pc = C_array; pp = P_array; ps = S_array - 4;
+
+    for ( i = 0 ; i < 64 ; i++ ) {
+       if ((i&0x0f) == 0) ps += 4;
+       temp = A;
+       switch (i>>4) {
+           case 0:
+               temp += FF(B,C,D);
+               break;
+           case 1:
+               temp += FG(B,C,D);
+               break;
+           case 2:
+               temp += FH(B,C,D);
+               break;
+           case 3:
+               temp += FI(B,C,D);
+       }
+       temp += cwp[(int)(*pp++)] + *pc++;
+       temp = CYCLIC (temp, ps[i&3]);
+       temp += B;
+       A = D; D = C; C = B; B = temp;
+    }
+#else
+    pc = C_array; pp = P_array; ps = S_array;
+
+    for ( i = 0 ; i < 16 ; i++ ) {
+       temp = A + FF(B,C,D) + cwp[(int)(*pp++)] + *pc++;
+       temp = CYCLIC (temp, ps[i&3]);
+       temp += B;
+       A = D; D = C; C = B; B = temp;
+    }
+
+    ps += 4;
+    for ( i = 0 ; i < 16 ; i++ ) {
+       temp = A + FG(B,C,D) + cwp[(int)(*pp++)] + *pc++;
+       temp = CYCLIC (temp, ps[i&3]);
+       temp += B;
+       A = D; D = C; C = B; B = temp;
+    }
+    ps += 4;
+    for ( i = 0 ; i < 16 ; i++ ) {
+       temp = A + FH(B,C,D) + cwp[(int)(*pp++)] + *pc++;
+       temp = CYCLIC (temp, ps[i&3]);
+       temp += B;
+       A = D; D = C; C = B; B = temp;
+    }
+    ps += 4;
+    for ( i = 0 ; i < 16 ; i++ ) {
+       temp = A + FI(B,C,D) + cwp[(int)(*pp++)] + *pc++;
+       temp = CYCLIC (temp, ps[i&3]);
+       temp += B;
+       A = D; D = C; C = B; B = temp;
+    }
+
+#endif
+#else
+    /* First round: using the given function, the context and a constant
+       the next context is computed.  Because the algorithms processing
+       unit is a 32-bit word and it is determined to work on words in
+       little endian byte order we perhaps have to change the byte order
+       before the computation.  To reduce the work for the next steps
+       we store the swapped words in the array CORRECT_WORDS.  */
+
+#define OP(a, b, c, d, s, T)                                           \
+      do                                                               \
+        {                                                              \
+         a += FF (b, c, d) + (*cwp++ = SWAP (*words)) + T;             \
+         ++words;                                                      \
+         CYCLIC (a, s);                                                \
+         a += b;                                                       \
+        }                                                              \
+      while (0)
+
+    /* It is unfortunate that C does not provide an operator for
+       cyclic rotation.  Hope the C compiler is smart enough.  */
+    /* gcc 2.95.4 seems to be --aaronl */
+#define CYCLIC(w, s) (w = (w << s) | (w >> (32 - s)))
+
+    /* Before we start, one word to the strange constants.
+       They are defined in RFC 1321 as
+
+       T[i] = (int) (4294967296.0 * fabs (sin (i))), i=1..64
+    */
+
+#if MD5SUM_SIZE_VS_SPEED == 1
+    const md5_uint32 *pc;
+    const char *pp;
+    int i;
+#endif
+
+    /* Round 1.  */
+#if MD5SUM_SIZE_VS_SPEED == 1
+    pc = C_array;
+    for ( i=0 ; i < 4 ; i++ ) {
+       OP(A, B, C, D, 7, *pc++);
+       OP(D, A, B, C, 12, *pc++);
+       OP(C, D, A, B, 17, *pc++);
+       OP(B, C, D, A, 22, *pc++);
+    }
+#else
+    OP(A, B, C, D, 7, 0xd76aa478);
+    OP(D, A, B, C, 12, 0xe8c7b756);
+    OP(C, D, A, B, 17, 0x242070db);
+    OP(B, C, D, A, 22, 0xc1bdceee);
+    OP(A, B, C, D, 7, 0xf57c0faf);
+    OP(D, A, B, C, 12, 0x4787c62a);
+    OP(C, D, A, B, 17, 0xa8304613);
+    OP(B, C, D, A, 22, 0xfd469501);
+    OP(A, B, C, D, 7, 0x698098d8);
+    OP(D, A, B, C, 12, 0x8b44f7af);
+    OP(C, D, A, B, 17, 0xffff5bb1);
+    OP(B, C, D, A, 22, 0x895cd7be);
+    OP(A, B, C, D, 7, 0x6b901122);
+    OP(D, A, B, C, 12, 0xfd987193);
+    OP(C, D, A, B, 17, 0xa679438e);
+    OP(B, C, D, A, 22, 0x49b40821);
+#endif
+
+    /* For the second to fourth round we have the possibly swapped words
+       in CORRECT_WORDS.  Redefine the macro to take an additional first
+       argument specifying the function to use.  */
+#undef OP
+#define OP(f, a, b, c, d, k, s, T)                                     \
+      do                                                               \
+       {                                                               \
+         a += f (b, c, d) + correct_words[k] + T;                      \
+         CYCLIC (a, s);                                                \
+         a += b;                                                       \
+       }                                                               \
+      while (0)
+
+    /* Round 2.  */
+#if MD5SUM_SIZE_VS_SPEED == 1
+    pp = P_array;
+    for ( i=0 ; i < 4 ; i++ ) {
+       OP(FG, A, B, C, D, (int)(*pp++), 5, *pc++);
+       OP(FG, D, A, B, C, (int)(*pp++), 9, *pc++);
+       OP(FG, C, D, A, B, (int)(*pp++), 14, *pc++);
+       OP(FG, B, C, D, A, (int)(*pp++), 20, *pc++);
+    }
+#else
+    OP(FG, A, B, C, D, 1, 5, 0xf61e2562);
+    OP(FG, D, A, B, C, 6, 9, 0xc040b340);
+    OP(FG, C, D, A, B, 11, 14, 0x265e5a51);
+    OP(FG, B, C, D, A, 0, 20, 0xe9b6c7aa);
+    OP(FG, A, B, C, D, 5, 5, 0xd62f105d);
+    OP(FG, D, A, B, C, 10, 9, 0x02441453);
+    OP(FG, C, D, A, B, 15, 14, 0xd8a1e681);
+    OP(FG, B, C, D, A, 4, 20, 0xe7d3fbc8);
+    OP(FG, A, B, C, D, 9, 5, 0x21e1cde6);
+    OP(FG, D, A, B, C, 14, 9, 0xc33707d6);
+    OP(FG, C, D, A, B, 3, 14, 0xf4d50d87);
+    OP(FG, B, C, D, A, 8, 20, 0x455a14ed);
+    OP(FG, A, B, C, D, 13, 5, 0xa9e3e905);
+    OP(FG, D, A, B, C, 2, 9, 0xfcefa3f8);
+    OP(FG, C, D, A, B, 7, 14, 0x676f02d9);
+    OP(FG, B, C, D, A, 12, 20, 0x8d2a4c8a);
+#endif
+
+    /* Round 3.  */
+#if MD5SUM_SIZE_VS_SPEED == 1
+    for ( i=0 ; i < 4 ; i++ ) {
+       OP(FH, A, B, C, D, (int)(*pp++), 4, *pc++);
+       OP(FH, D, A, B, C, (int)(*pp++), 11, *pc++);
+       OP(FH, C, D, A, B, (int)(*pp++), 16, *pc++);
+       OP(FH, B, C, D, A, (int)(*pp++), 23, *pc++);
+    }
+#else
+    OP(FH, A, B, C, D, 5, 4, 0xfffa3942);
+    OP(FH, D, A, B, C, 8, 11, 0x8771f681);
+    OP(FH, C, D, A, B, 11, 16, 0x6d9d6122);
+    OP(FH, B, C, D, A, 14, 23, 0xfde5380c);
+    OP(FH, A, B, C, D, 1, 4, 0xa4beea44);
+    OP(FH, D, A, B, C, 4, 11, 0x4bdecfa9);
+    OP(FH, C, D, A, B, 7, 16, 0xf6bb4b60);
+    OP(FH, B, C, D, A, 10, 23, 0xbebfbc70);
+    OP(FH, A, B, C, D, 13, 4, 0x289b7ec6);
+    OP(FH, D, A, B, C, 0, 11, 0xeaa127fa);
+    OP(FH, C, D, A, B, 3, 16, 0xd4ef3085);
+    OP(FH, B, C, D, A, 6, 23, 0x04881d05);
+    OP(FH, A, B, C, D, 9, 4, 0xd9d4d039);
+    OP(FH, D, A, B, C, 12, 11, 0xe6db99e5);
+    OP(FH, C, D, A, B, 15, 16, 0x1fa27cf8);
+    OP(FH, B, C, D, A, 2, 23, 0xc4ac5665);
+#endif
+
+    /* Round 4.  */
+#if MD5SUM_SIZE_VS_SPEED == 1
+    for ( i=0 ; i < 4 ; i++ ) {
+       OP(FI, A, B, C, D, (int)(*pp++), 6, *pc++);
+       OP(FI, D, A, B, C, (int)(*pp++), 10, *pc++);
+       OP(FI, C, D, A, B, (int)(*pp++), 15, *pc++);
+       OP(FI, B, C, D, A, (int)(*pp++), 21, *pc++);
+    }
+#else
+    OP(FI, A, B, C, D, 0, 6, 0xf4292244);
+    OP(FI, D, A, B, C, 7, 10, 0x432aff97);
+    OP(FI, C, D, A, B, 14, 15, 0xab9423a7);
+    OP(FI, B, C, D, A, 5, 21, 0xfc93a039);
+    OP(FI, A, B, C, D, 12, 6, 0x655b59c3);
+    OP(FI, D, A, B, C, 3, 10, 0x8f0ccc92);
+    OP(FI, C, D, A, B, 10, 15, 0xffeff47d);
+    OP(FI, B, C, D, A, 1, 21, 0x85845dd1);
+    OP(FI, A, B, C, D, 8, 6, 0x6fa87e4f);
+    OP(FI, D, A, B, C, 15, 10, 0xfe2ce6e0);
+    OP(FI, C, D, A, B, 6, 15, 0xa3014314);
+    OP(FI, B, C, D, A, 13, 21, 0x4e0811a1);
+    OP(FI, A, B, C, D, 4, 6, 0xf7537e82);
+    OP(FI, D, A, B, C, 11, 10, 0xbd3af235);
+    OP(FI, C, D, A, B, 2, 15, 0x2ad7d2bb);
+    OP(FI, B, C, D, A, 9, 21, 0xeb86d391);
+#endif
+#endif
+
+    /* Add the starting values of the context.  */
+    A += A_save;
+    B += B_save;
+    C += C_save;
+    D += D_save;
+  }
+
+  /* Put checksum in context given as argument.  */
+  ctx->A = A;
+  ctx->B = B;
+  ctx->C = C;
+  ctx->D = D;
+}
+
+//----------------------------------------------------------------------------
+//--------end of md5.c
+//----------------------------------------------------------------------------
+
+#define ISWHITE(c) ((c) == ' ' || (c) == '\t')
+#define ISXDIGIT(c) (isxdigit (c))
+
+/* The minimum length of a valid digest line in a file produced
+   by `md5sum FILE' and read by `md5sum -c'.  This length does
+   not include any newline character at the end of a line.  */
+static const int MIN_DIGEST_LINE_LENGTH = 35; /* 32 - message digest length
+                                      2 - blank and binary indicator
+                                      1 - minimum filename length */
+
+static inline int hex_digits(unsigned char const *s)
+{
+  while (*s) {
+    if (!ISXDIGIT(*s))
+      return 0;
+    ++s;
+  }
+  return 1;
+}
+
+
diff --git a/libopkg/md5.h b/libopkg/md5.h
new file mode 100644 (file)
index 0000000..7af7e93
--- /dev/null
@@ -0,0 +1,35 @@
+/* md5.h - Compute MD5 checksum of files or strings according to the
+ *         definition of MD5 in RFC 1321 from April 1992.
+ * Copyright (C) 1995-1999 Free Software Foundation, Inc.
+ *
+ * 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, 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 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.
+ */
+
+#ifndef MD5_H
+#define MD5_H
+
+/* Compute MD5 message digest for bytes read from STREAM.  The
+   resulting message digest number will be written into the 16 bytes
+   beginning at RESBLOCK.  */
+int md5_stream(FILE *stream, void *resblock);
+
+/* Compute MD5 message digest for LEN bytes beginning at BUFFER.  The
+   result is always in little endian byte order, so that a byte-wise
+   output yields to the wanted ASCII representation of the message
+   digest.  */
+void *md5_buffer(const char *buffer, size_t len, void *resblock);
+
+#endif
+
diff --git a/libopkg/nv_pair.c b/libopkg/nv_pair.c
new file mode 100644 (file)
index 0000000..75a08e8
--- /dev/null
@@ -0,0 +1,40 @@
+/* nv_pair.c - the itsy package management system
+
+   Carl D. Worth
+
+   Copyright (C) 2001 University of Southern California
+
+   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, 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
+   General Public License for more details.
+*/
+
+#include "opkg.h"
+
+#include "nv_pair.h"
+#include "str_util.h"
+
+int nv_pair_init(nv_pair_t *nv_pair, const char *name, const char *value)
+{
+    nv_pair->name = str_dup_safe(name);
+    nv_pair->value = str_dup_safe(value);
+
+    return 0;
+}
+
+void nv_pair_deinit(nv_pair_t *nv_pair)
+{
+    free(nv_pair->name);
+    nv_pair->name = NULL;
+
+    free(nv_pair->value);
+    nv_pair->value = NULL;
+}
+
+
diff --git a/libopkg/nv_pair.h b/libopkg/nv_pair.h
new file mode 100644 (file)
index 0000000..664eab8
--- /dev/null
@@ -0,0 +1,32 @@
+/* nv_pair.h - the itsy package management system
+
+   Carl D. Worth
+
+   Copyright (C) 2001 University of Southern California
+
+   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, 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
+   General Public License for more details.
+*/
+
+#ifndef NV_PAIR_H
+#define NV_PAIR_H
+
+typedef struct nv_pair nv_pair_t;
+struct nv_pair
+{
+    char *name;
+    char *value;
+};
+
+int nv_pair_init(nv_pair_t *nv_pair, const char *name, const char *value);
+void nv_pair_deinit(nv_pair_t *nv_pair);
+
+#endif
+
diff --git a/libopkg/nv_pair_list.c b/libopkg/nv_pair_list.c
new file mode 100644 (file)
index 0000000..b925322
--- /dev/null
@@ -0,0 +1,98 @@
+/* nv_pair_list.c - the itsy package management system
+
+   Carl D. Worth
+
+   Copyright (C) 2001 University of Southern California
+
+   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, 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
+   General Public License for more details.
+*/
+
+#include "opkg.h"
+
+#include "nv_pair.h"
+#include "void_list.h"
+#include "nv_pair_list.h"
+
+int nv_pair_list_elt_init(nv_pair_list_elt_t *elt, nv_pair_t *data)
+{
+    return void_list_elt_init((void_list_elt_t *) elt, data);
+}
+
+void nv_pair_list_elt_deinit(nv_pair_list_elt_t *elt)
+{
+    void_list_elt_deinit((void_list_elt_t *) elt);
+}
+
+int nv_pair_list_init(nv_pair_list_t *list)
+{
+    return void_list_init((void_list_t *) list);
+}
+
+void nv_pair_list_deinit(nv_pair_list_t *list)
+{
+    nv_pair_list_elt_t *iter;
+    nv_pair_t *nv_pair;
+
+    for (iter = list->head; iter; iter = iter->next) {
+       nv_pair = iter->data;
+       nv_pair_deinit(nv_pair);
+
+       /* malloced in nv_pair_list_append */
+       free(nv_pair);
+       iter->data = NULL;
+    }
+    void_list_deinit((void_list_t *) list);
+}
+
+nv_pair_t *nv_pair_list_append(nv_pair_list_t *list, const char *name, const char *value)
+{
+    int err;
+
+    /* freed in nv_pair_list_deinit */
+    nv_pair_t *nv_pair = malloc(sizeof(nv_pair_t));
+
+    if (nv_pair == NULL) {
+       fprintf(stderr, "%s: out of memory\n", __FUNCTION__);
+       return NULL;
+    }
+    nv_pair_init(nv_pair, name, value);
+
+    err = void_list_append((void_list_t *) list, nv_pair);
+    if (err) {
+       return NULL;
+    }
+
+    return nv_pair;
+}
+
+int nv_pair_list_push(nv_pair_list_t *list, nv_pair_t *data)
+{
+    return void_list_push((void_list_t *) list, data);
+}
+
+nv_pair_list_elt_t *nv_pair_list_pop(nv_pair_list_t *list)
+{
+    return (nv_pair_list_elt_t *) void_list_pop((void_list_t *) list);
+}
+
+char *nv_pair_list_find(nv_pair_list_t *list, char *name)
+{
+     nv_pair_list_elt_t *iter;
+     nv_pair_t *nv_pair;
+
+     for (iter = list->head; iter; iter = iter->next) {
+         nv_pair = iter->data;
+         if (strcmp(nv_pair->name, name) == 0) {
+              return nv_pair->value;
+         }
+     }    
+     return NULL;
+}
diff --git a/libopkg/nv_pair_list.h b/libopkg/nv_pair_list.h
new file mode 100644 (file)
index 0000000..8638dd1
--- /dev/null
@@ -0,0 +1,60 @@
+/* nv_pair_list.h - the itsy package management system
+
+   Carl D. Worth
+
+   Copyright (C) 2001 University of Southern California
+
+   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, 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
+   General Public License for more details.
+*/
+
+#ifndef NV_PAIR_LIST_H
+#define NV_PAIR_LIST_H
+
+#include "nv_pair.h"
+#include "void_list.h"
+
+typedef struct nv_pair_list_elt nv_pair_list_elt_t;
+struct nv_pair_list_elt
+{
+    nv_pair_list_elt_t *next;
+    nv_pair_t *data;
+};
+
+typedef struct nv_pair_list nv_pair_list_t;
+struct nv_pair_list
+{
+    nv_pair_list_elt_t pre_head;
+    nv_pair_list_elt_t *head;
+    nv_pair_list_elt_t *tail;
+};
+
+static inline int nv_pair_list_empty(nv_pair_list_t *list)
+{
+     if (list->head == NULL)
+         return 1;
+     else
+         return 0;
+}
+
+int nv_pair_list_elt_init(nv_pair_list_elt_t *elt, nv_pair_t *data);
+void nv_pair_list_elt_deinit(nv_pair_list_elt_t *elt);
+
+int nv_pair_list_init(nv_pair_list_t *list);
+void nv_pair_list_deinit(nv_pair_list_t *list);
+
+nv_pair_t *nv_pair_list_append(nv_pair_list_t *list,
+                              const char *name, const char *value);
+int nv_pair_list_push(nv_pair_list_t *list, nv_pair_t *data);
+nv_pair_list_elt_t *nv_pair_list_pop(nv_pair_list_t *list);
+char *nv_pair_list_find(nv_pair_list_t *list, char *name);
+
+#endif
+
diff --git a/libopkg/opkg.c b/libopkg/opkg.c
new file mode 100644 (file)
index 0000000..e113847
--- /dev/null
@@ -0,0 +1,81 @@
+/* opkg.c - the itsy package management system
+
+   Carl D. Worth
+
+   Copyright (C) 2001 University of Southern California
+
+   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, 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
+   General Public License for more details.
+*/
+
+#include "opkg.h"
+
+#include "args.h"
+#include "opkg_conf.h"
+#include "opkg_cmd.h"
+
+int main(int argc, const char *argv[])
+{
+    int err, optind;
+    args_t args;
+    char *cmd_name;
+    opkg_cmd_t *cmd;
+    opkg_conf_t opkg_conf;
+
+    error_list=NULL;
+
+    args_init(&args);
+       
+    optind = args_parse(&args, argc, argv);
+    if (optind == argc || optind < 0) {
+       args_usage("opkg must have one sub-command argument");
+    }
+
+    cmd_name = argv[optind++];
+
+    err = opkg_conf_init(&opkg_conf, &args);
+    if (err) {
+       return err;
+    }
+
+    args_deinit(&args);
+
+    cmd = opkg_cmd_find(cmd_name);
+    if (cmd == NULL) {
+       fprintf(stderr, "%s: unknown sub-command %s\n", argv[0], cmd_name);
+       args_usage(NULL);
+    }
+
+    if (cmd->requires_args && optind == argc) {
+       fprintf(stderr, "%s: the ``%s'' command requires at least one argument\n",
+               __FUNCTION__, cmd_name);
+       args_usage(NULL);
+    }
+
+    err = opkg_cmd_exec(cmd, &opkg_conf, argc - optind, argv + optind);
+
+    if ( err == 0 ) {
+       opkg_message(opkg_conf, OPKG_NOTICE, "Succesfully done.\n");
+    } else {
+       opkg_message(opkg_conf, OPKG_NOTICE, "Error returned. Return value is %d\n.",err);
+
+}
+
+    }
+    /* XXX: FEATURE request: run ldconfig and/or depmod after package needing them are installed or removed */  
+    // opkg_global_postinst();
+
+    opkg_conf_deinit(&opkg_conf);
+
+    return err;
+}
+
+
+
diff --git a/libopkg/opkg.h b/libopkg/opkg.h
new file mode 100644 (file)
index 0000000..b6a793d
--- /dev/null
@@ -0,0 +1,68 @@
+/* opkg.h - the itsy package management system
+
+   Carl D. Worth
+
+   Copyright (C) 2001 University of Southern California
+
+   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, 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
+   General Public License for more details.
+*/
+
+#ifndef OPKG_H
+#define OPKG_H
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#if 0
+#define OPKG_DEBUG_NO_TMP_CLEANUP
+#endif
+
+#include "includes.h"
+#include "opkg_conf.h"
+#include "opkg_message.h"
+
+#define OPKG_PKG_EXTENSION ".ipk"
+#define DPKG_PKG_EXTENSION ".deb"
+
+#define OPKG_LEGAL_PKG_NAME_CHARS "abcdefghijklmnopqrstuvwxyz0123456789.+-"
+#define OPKG_PKG_VERSION_SEP_CHAR '_'
+
+#define OPKG_STATE_DIR_PREFIX OPKGLIBDIR"/opkg"
+#define OPKG_LISTS_DIR_SUFFIX "lists"
+#define OPKG_INFO_DIR_SUFFIX "info"
+#define OPKG_STATUS_FILE_SUFFIX "status"
+
+#define OPKG_BACKUP_SUFFIX "-opkg.backup"
+
+#define OPKG_LIST_DESCRIPTION_LENGTH 128
+
+enum opkg_error {
+    OPKG_SUCCESS = 0,
+    OPKG_PKG_DEPS_UNSATISFIED,
+    OPKG_PKG_IS_ESSENTIAL,
+    OPKG_PKG_HAS_DEPENDENTS,
+    OPKG_PKG_HAS_NO_CANDIDATE
+};
+typedef enum opkg_error opkg_error_t;
+
+extern int opkg_state_changed;
+
+
+struct errlist {
+    char * errmsg;
+    struct errlist * next;
+} ;
+
+struct errlist* error_list;
+
+
+#endif
diff --git a/libopkg/opkg_cmd.c b/libopkg/opkg_cmd.c
new file mode 100644 (file)
index 0000000..db04a4a
--- /dev/null
@@ -0,0 +1,1467 @@
+/* opkg_cmd.c - the itsy package management system
+
+   Carl D. Worth
+
+   Copyright (C) 2001 University of Southern California
+
+   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, 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
+   General Public License for more details.
+*/
+
+#include <string.h>
+
+#include "opkg.h"
+#include <libgen.h>
+#include <glob.h>
+#include <errno.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <signal.h>
+#include <stdio.h>
+#include <dirent.h>
+
+#include "opkg_conf.h"
+#include "opkg_cmd.h"
+#include "opkg_message.h"
+#include "pkg.h"
+#include "pkg_dest.h"
+#include "pkg_parse.h"
+#include "sprintf_alloc.h"
+#include "pkg.h"
+#include "file_util.h"
+#include "str_util.h"
+#include "libbb/libbb.h"
+
+#include <fnmatch.h>
+
+
+#include "opkg_download.h"
+#include "opkg_install.h"
+#include "opkg_upgrade.h"
+#include "opkg_remove.h"
+#include "opkg_configure.h"
+#include "opkg_message.h"
+
+#ifdef OPKG_LIB
+#include "libopkg.h"
+static void *p_userdata = NULL;
+#endif
+
+static int opkg_update_cmd(opkg_conf_t *conf, int argc, char **argv);
+static int opkg_upgrade_cmd(opkg_conf_t *conf, int argc, char **argv);
+static int opkg_list_cmd(opkg_conf_t *conf, int argc, char **argv);
+static int opkg_info_cmd(opkg_conf_t *conf, int argc, char **argv);
+static int opkg_status_cmd(opkg_conf_t *conf, int argc, char **argv);
+static int opkg_install_pending_cmd(opkg_conf_t *conf, int argc, char **argv);
+static int opkg_install_cmd(opkg_conf_t *conf, int argc, char **argv);
+static int opkg_list_installed_cmd(opkg_conf_t *conf, int argc, char **argv);
+static int opkg_remove_cmd(opkg_conf_t *conf, int argc, char **argv);
+static int opkg_purge_cmd(opkg_conf_t *conf, int argc, char **argv);
+static int opkg_flag_cmd(opkg_conf_t *conf, int argc, char **argv);
+static int opkg_files_cmd(opkg_conf_t *conf, int argc, char **argv);
+static int opkg_search_cmd(opkg_conf_t *conf, int argc, char **argv);
+static int opkg_download_cmd(opkg_conf_t *conf, int argc, char **argv);
+static int opkg_depends_cmd(opkg_conf_t *conf, int argc, char **argv);
+static int opkg_whatdepends_cmd(opkg_conf_t *conf, int argc, char **argv);
+static int opkg_whatdepends_recursively_cmd(opkg_conf_t *conf, int argc, char **argv);
+static int opkg_whatsuggests_cmd(opkg_conf_t *conf, int argc, char **argv);
+static int opkg_whatrecommends_cmd(opkg_conf_t *conf, int argc, char **argv);
+static int opkg_whatprovides_cmd(opkg_conf_t *conf, int argc, char **argv);
+static int opkg_whatconflicts_cmd(opkg_conf_t *conf, int argc, char **argv);
+static int opkg_whatreplaces_cmd(opkg_conf_t *conf, int argc, char **argv);
+static int opkg_compare_versions_cmd(opkg_conf_t *conf, int argc, char **argv);
+static int opkg_print_architecture_cmd(opkg_conf_t *conf, int argc, char **argv);
+static int opkg_configure_cmd(opkg_conf_t *conf, int argc, char **argv);
+
+/* XXX: CLEANUP: The usage strings should be incorporated into this
+   array for easier maintenance */
+static opkg_cmd_t cmds[] = {
+     {"update", 0, (opkg_cmd_fun_t)opkg_update_cmd}, 
+     {"upgrade", 0, (opkg_cmd_fun_t)opkg_upgrade_cmd},
+     {"list", 0, (opkg_cmd_fun_t)opkg_list_cmd},
+     {"list_installed", 0, (opkg_cmd_fun_t)opkg_list_installed_cmd},
+     {"info", 0, (opkg_cmd_fun_t)opkg_info_cmd},
+     {"flag", 1, (opkg_cmd_fun_t)opkg_flag_cmd},
+     {"status", 0, (opkg_cmd_fun_t)opkg_status_cmd},
+     {"install_pending", 0, (opkg_cmd_fun_t)opkg_install_pending_cmd},
+     {"install", 1, (opkg_cmd_fun_t)opkg_install_cmd},
+     {"remove", 1, (opkg_cmd_fun_t)opkg_remove_cmd},
+     {"purge", 1, (opkg_cmd_fun_t)opkg_purge_cmd},
+     {"configure", 0, (opkg_cmd_fun_t)opkg_configure_cmd},
+     {"files", 1, (opkg_cmd_fun_t)opkg_files_cmd},
+     {"search", 1, (opkg_cmd_fun_t)opkg_search_cmd},
+     {"download", 1, (opkg_cmd_fun_t)opkg_download_cmd},
+     {"compare_versions", 1, (opkg_cmd_fun_t)opkg_compare_versions_cmd},
+     {"compare-versions", 1, (opkg_cmd_fun_t)opkg_compare_versions_cmd},
+     {"print-architecture", 0, (opkg_cmd_fun_t)opkg_print_architecture_cmd},
+     {"print_architecture", 0, (opkg_cmd_fun_t)opkg_print_architecture_cmd},
+     {"print-installation-architecture", 0, (opkg_cmd_fun_t)opkg_print_architecture_cmd},
+     {"print_installation_architecture", 0, (opkg_cmd_fun_t)opkg_print_architecture_cmd},
+     {"depends", 1, (opkg_cmd_fun_t)opkg_depends_cmd},
+     {"whatdepends", 1, (opkg_cmd_fun_t)opkg_whatdepends_cmd},
+     {"whatdependsrec", 1, (opkg_cmd_fun_t)opkg_whatdepends_recursively_cmd},
+     {"whatrecommends", 1, (opkg_cmd_fun_t)opkg_whatrecommends_cmd},
+     {"whatsuggests", 1, (opkg_cmd_fun_t)opkg_whatsuggests_cmd},
+     {"whatprovides", 1, (opkg_cmd_fun_t)opkg_whatprovides_cmd},
+     {"whatreplaces", 1, (opkg_cmd_fun_t)opkg_whatreplaces_cmd},
+     {"whatconflicts", 1, (opkg_cmd_fun_t)opkg_whatconflicts_cmd},
+};
+
+int opkg_state_changed;
+static void write_status_files_if_changed(opkg_conf_t *conf)
+{
+     if (opkg_state_changed && !conf->noaction) {
+         opkg_message(conf, OPKG_INFO,
+                      "  writing status file\n");
+         opkg_conf_write_status_files(conf);
+         pkg_write_changed_filelists(conf);
+     } else { 
+         opkg_message(conf, OPKG_NOTICE, "Nothing to be done\n");
+     }
+}
+
+
+static int num_cmds = sizeof(cmds) / sizeof(opkg_cmd_t);
+
+opkg_cmd_t *opkg_cmd_find(const char *name)
+{
+     int i;
+     opkg_cmd_t *cmd;
+
+     for (i=0; i < num_cmds; i++) {
+         cmd = &cmds[i];
+         if (strcmp(name, cmd->name) == 0) {
+              return cmd;
+         }
+     }
+
+     return NULL;
+}
+
+#ifdef OPKG_LIB
+int opkg_cmd_exec(opkg_cmd_t *cmd, opkg_conf_t *conf, int argc, const char **argv, void *userdata)
+{
+       int result;
+       p_userdata = userdata;
+      
+
+       result = (cmd->fun)(conf, argc, argv);
+
+        if ( result != 0 ) {
+           opkg_message(conf, OPKG_NOTICE, "An error ocurred, return value: %d.\n", result);
+        }
+
+        if ( error_list ) {
+           reverse_error_list(&error_list);
+
+           opkg_message(conf, OPKG_NOTICE, "Collected errors:\n");
+           /* Here we print the errors collected and free the list */
+           while (error_list != NULL) {
+                 opkg_message(conf, OPKG_NOTICE, "%s",error_list->errmsg);
+                 error_list = error_list->next;
+
+           }
+           free_error_list(&error_list);
+
+        }
+   
+       p_userdata = NULL;
+       return result;
+}
+#else
+int opkg_cmd_exec(opkg_cmd_t *cmd, opkg_conf_t *conf, int argc, const char **argv)
+{
+     return (cmd->fun)(conf, argc, argv);
+}
+#endif
+
+static int opkg_update_cmd(opkg_conf_t *conf, int argc, char **argv)
+{
+     int err;
+     int failures;
+     char *lists_dir;
+     pkg_src_list_elt_t *iter;
+     pkg_src_t *src;
+
+    sprintf_alloc(&lists_dir, "%s", conf->restrict_to_default_dest ? conf->default_dest->lists_dir : conf->lists_dir);
+    if (! file_is_dir(lists_dir)) {
+         if (file_exists(lists_dir)) {
+              opkg_message(conf, OPKG_ERROR,
+                           "%s: ERROR: %s exists, but is not a directory\n",
+                           __FUNCTION__, lists_dir);
+              free(lists_dir);
+              return EINVAL;
+         }
+         err = file_mkdir_hier(lists_dir, 0755);
+         if (err) {
+              opkg_message(conf, OPKG_ERROR,
+                           "%s: ERROR: failed to make directory %s: %s\n",
+                           __FUNCTION__, lists_dir, strerror(errno));
+              free(lists_dir);
+              return EINVAL;
+         }     
+     } 
+
+     failures = 0;
+     for (iter = conf->pkg_src_list.head; iter; iter = iter->next) {
+         char *url, *list_file_name;
+
+         src = iter->data;
+
+         if (src->extra_data)  /* debian style? */
+             sprintf_alloc(&url, "%s/%s/%s", src->value, src->extra_data, 
+                           src->gzip ? "Packages.gz" : "Packages");
+         else
+             sprintf_alloc(&url, "%s/%s", src->value, src->gzip ? "Packages.gz" : "Packages");
+
+         sprintf_alloc(&list_file_name, "%s/%s", lists_dir, src->name);
+         if (src->gzip) {
+             char *tmp;
+             char *tmp_file_name;
+             FILE *in, *out;
+
+             tmp = strdup ("/tmp/opkg.XXXXXX");
+
+             if (mkdtemp (tmp) == NULL) {
+                 perror ("mkdtemp");
+                 failures++;
+                 continue;
+             }
+             
+             sprintf_alloc (&tmp_file_name, "%s/%s.gz", tmp, src->name);
+             err = opkg_download(conf, url, tmp_file_name);
+             if (err == 0) {
+                  opkg_message (conf, OPKG_NOTICE, "Inflating %s\n", url);
+                  in = fopen (tmp_file_name, "r");
+                  out = fopen (list_file_name, "w");
+                  if (in && out)
+                       unzip (in, out);
+                  else
+                       err = 1;
+                  if (in)
+                       fclose (in);
+                  if (out)
+                       fclose (out);
+                  unlink (tmp_file_name);
+                  rmdir (tmp);
+                  free (tmp);
+             }
+         } else
+             err = opkg_download(conf, url, list_file_name);
+         if (err) {
+              failures++;
+         } else {
+              opkg_message(conf, OPKG_NOTICE,
+                           "Updated list of available packages in %s\n",
+                           list_file_name);
+         }
+         free(url);
+
+         /* download detached signitures to verify the package lists */
+         /* get the url for the sig file */
+         if (src->extra_data)  /* debian style? */
+             sprintf_alloc(&url, "%s/%s/%s", src->value, src->extra_data,
+                           "Packages.sig");
+         else
+             sprintf_alloc(&url, "%s/%s", src->value, "Packages.sig");
+
+         /* create temporary dir for it */
+         char *tmp, *tmp_file_name;
+         tmp = strdup ("/tmp/opkg.XXXXXX");
+         if (mkdtemp (tmp) == NULL) {
+               perror ("mkdtemp");
+               failures++;
+               continue;
+         }
+         sprintf_alloc (&tmp_file_name, "%s/%s", tmp, "Packages.sig");
+
+         err = opkg_download(conf, url, tmp_file_name);
+         if (err) {
+           failures++;
+               opkg_message (conf, OPKG_NOTICE, "Signature check failed\n");
+         } else {
+           int err;
+           err = opkg_verify_file (list_file_name, tmp_file_name);
+           if (err == 0)
+               opkg_message (conf, OPKG_NOTICE, "Signature check passed\n");
+           else
+               opkg_message (conf, OPKG_NOTICE, "Signature check failed\n");
+         }
+         unlink (tmp_file_name);
+         unlink (tmp);
+         free (tmp_file_name);
+
+         free (url);
+         free(list_file_name);
+     }
+     free(lists_dir);
+
+#ifdef CONFIG_CLEAR_SW_INSTALL_FLAG
+#warning here
+     /* clear SW_INSTALL on any package where state is SS_NOT_INSTALLED.
+      * this is a hack to work around poor bookkeeping in old opkg upgrade code 
+      * -Jamey 3/1/03
+      */
+     {
+         int i;
+         int changed = 0;
+         pkg_vec_t *available = pkg_vec_alloc();
+         pkg_hash_fetch_available(&conf->pkg_hash, available);
+         opkg_message(conf, OPKG_DEBUG, "Clearing SW_INSTALL for SS_NOT_INSTALLED packages.\n");
+         for (i = 0; i < available->len; i++) {
+              pkg_t *pkg = available->pkgs[i];
+              if (pkg->state_want == SW_INSTALL && pkg->state_status == SS_NOT_INSTALLED) {
+                   opkg_message(conf, OPKG_DEBUG, "Clearing SW_INSTALL on package %s.\n", pkg->name);
+                   pkg->state_want = SW_UNKNOWN;
+                   changed = 1;
+              }
+         }
+         pkg_vec_free(available);
+         if (changed) {
+              write_status_files_if_changed(conf);
+         }
+     }
+#endif
+
+     return failures;
+}
+
+
+/* scan the args passed and cache the local filenames of the packages */
+int opkg_multiple_files_scan(opkg_conf_t *conf, int argc, char **argv)
+{
+     int i;
+     int err;
+    
+     /* 
+      * First scan through package names/urls
+      * For any urls, download the packages and install in database.
+      * For any files, install package info in database.
+      */
+     for (i = 0; i < argc; i ++) {
+         char *filename = argv [i];
+         //char *tmp = basename (tmp);
+         //int tmplen = strlen (tmp);
+
+         //if (strcmp (tmp + (tmplen - strlen (OPKG_PKG_EXTENSION)), OPKG_PKG_EXTENSION) != 0)
+         //     continue;
+         //if (strcmp (tmp + (tmplen - strlen (DPKG_PKG_EXTENSION)), DPKG_PKG_EXTENSION) != 0)
+         //     continue;
+       
+          opkg_message(conf, OPKG_DEBUG2, "Debug mfs: %s  \n",filename );
+
+         err = opkg_prepare_url_for_install(conf, filename, &argv[i]);
+         if (err)
+           return err;
+     }
+     return 0;
+}
+
+struct opkg_intercept
+{
+    char *oldpath;
+    char *statedir;
+};
+
+typedef struct opkg_intercept *opkg_intercept_t;
+
+opkg_intercept_t opkg_prep_intercepts(opkg_conf_t *conf)
+{
+    opkg_intercept_t ctx;
+    char *newpath;
+    int gen;
+
+    ctx = malloc (sizeof (*ctx));
+    ctx->oldpath = strdup (getenv ("PATH"));
+
+    sprintf_alloc (&newpath, "%s/opkg/intercept:%s", DATADIR, ctx->oldpath);
+    setenv ("PATH", newpath, 1);
+    free (newpath);
+    
+    gen = 0;
+ retry:
+    sprintf_alloc (&ctx->statedir, "/tmp/opkg-intercept-%d-%d", getpid (), gen);
+    if (mkdir (ctx->statedir, 0770) < 0) {
+       if (errno == EEXIST) {
+           free (ctx->statedir);
+           gen++;
+           goto retry;
+       }
+       perror (ctx->statedir);
+       return NULL;
+    }
+    setenv ("OPKG_INTERCEPT_DIR", ctx->statedir, 1);
+    return ctx;
+}
+
+int opkg_finalize_intercepts(opkg_intercept_t ctx)
+{
+    char *cmd;
+    DIR *dir;
+    int err = 0;
+
+    setenv ("PATH", ctx->oldpath, 1);
+    free (ctx->oldpath);
+
+    dir = opendir (ctx->statedir);
+    if (dir) {
+       struct dirent *de;
+       while (de = readdir (dir), de != NULL) {
+           char *path;
+           
+           if (de->d_name[0] == '.')
+               continue;
+           
+           sprintf_alloc (&path, "%s/%s", ctx->statedir, de->d_name);
+           if (access (path, X_OK) == 0) {
+               if (system (path)) {
+                   err = errno;
+                   perror (de->d_name);
+               }
+           }
+           free (path);
+       }
+    } else
+       perror (ctx->statedir);
+       
+    sprintf_alloc (&cmd, "rm -rf %s", ctx->statedir);
+    system (cmd);
+    free (cmd);
+
+    free (ctx->statedir);
+    free (ctx);
+
+    return err;
+}
+
+int opkg_configure_packages(opkg_conf_t *conf, char *pkg_name)
+{
+     pkg_vec_t *all;
+     int i;
+     pkg_t *pkg;
+     opkg_intercept_t ic;
+     int r, err = 0;
+
+     opkg_message(conf, OPKG_INFO,
+                 "Configuring unpacked packages\n");
+     fflush( stdout );
+
+     all = pkg_vec_alloc();
+     pkg_hash_fetch_available(&conf->pkg_hash, all);
+
+     ic = opkg_prep_intercepts (conf);
+    
+     for(i = 0; i < all->len; i++) {
+         pkg = all->pkgs[i];
+
+         if (pkg_name && fnmatch(pkg_name, pkg->name, 0)) 
+              continue;
+
+         if (pkg->state_status == SS_UNPACKED) {
+              opkg_message(conf, OPKG_NOTICE,
+                           "Configuring %s\n", pkg->name);
+              fflush( stdout );
+              r = opkg_configure(conf, pkg);
+              if (r == 0) {
+                   pkg->state_status = SS_INSTALLED;
+                   pkg->parent->state_status = SS_INSTALLED;
+                   pkg->state_flag &= ~SF_PREFER;
+              } else {
+                   if (!err)
+                       err = r;
+              }
+         }
+     }
+
+     r = opkg_finalize_intercepts (ic);
+     if (r && !err)
+        err = r;
+
+     pkg_vec_free(all);
+     return err;
+}
+
+static opkg_conf_t *global_conf;
+
+static void sigint_handler(int sig)
+{
+     signal(sig, SIG_DFL);
+     opkg_message(NULL, OPKG_NOTICE,
+                 "opkg: interrupted. writing out status database\n");
+     write_status_files_if_changed(global_conf);
+     exit(128 + sig);
+}
+
+static int opkg_install_cmd(opkg_conf_t *conf, int argc, char **argv)
+{
+     int i;
+     char *arg;
+     int err=0;
+
+     global_conf = conf;
+     signal(SIGINT, sigint_handler);
+
+     /*
+      * Now scan through package names and install
+      */
+     for (i=0; i < argc; i++) {
+         arg = argv[i];
+
+          opkg_message(conf, OPKG_DEBUG2, "Debug install_cmd: %s  \n",arg );
+          err = opkg_prepare_url_for_install(conf, arg, &argv[i]);
+          if (err != EINVAL && err != 0)
+              return err;
+     }
+     pkg_info_preinstall_check(conf);
+
+     for (i=0; i < argc; i++) {
+         arg = argv[i];
+         if (conf->multiple_providers)
+              err = opkg_install_multi_by_name(conf, arg);
+         else{
+              err = opkg_install_by_name(conf, arg);
+          }
+         if (err == OPKG_PKG_HAS_NO_CANDIDATE) {
+              opkg_message(conf, OPKG_ERROR,
+                           "Cannot find package %s.\n"
+                           "Check the spelling or perhaps run 'opkg update'\n",
+                           arg);
+         }
+     }
+
+     /* recheck to verify that all dependences are satisfied */
+     if (0) opkg_satisfy_all_dependences(conf);
+
+     opkg_configure_packages(conf, NULL);
+
+     write_status_files_if_changed(conf);
+
+     return err;
+}
+
+static int opkg_upgrade_cmd(opkg_conf_t *conf, int argc, char **argv)
+{
+     int i;
+     pkg_t *pkg;
+     int err;
+
+     global_conf = conf;
+     signal(SIGINT, sigint_handler);
+
+     if (argc) {
+         for (i=0; i < argc; i++) {
+              char *arg = argv[i];
+
+               err = opkg_prepare_url_for_install(conf, arg, &arg);
+               if (err != EINVAL && err != 0)
+                   return err;
+         }
+         pkg_info_preinstall_check(conf);
+
+         for (i=0; i < argc; i++) {
+              char *arg = argv[i];
+              if (conf->restrict_to_default_dest) {
+                   pkg = pkg_hash_fetch_installed_by_name_dest(&conf->pkg_hash,
+                                                               argv[i],
+                                                               conf->default_dest);
+                   if (pkg == NULL) {
+                        opkg_message(conf, OPKG_NOTICE,
+                                     "Package %s not installed in %s\n",
+                                     argv[i], conf->default_dest->name);
+                        continue;
+                   }
+              } else {
+                   pkg = pkg_hash_fetch_installed_by_name(&conf->pkg_hash,
+                                                          argv[i]);
+              }
+              if (pkg)
+                   opkg_upgrade_pkg(conf, pkg);
+              else {
+                   opkg_install_by_name(conf, arg);
+               }
+         }
+     } else {
+         pkg_vec_t *installed = pkg_vec_alloc();
+
+         pkg_info_preinstall_check(conf);
+
+         pkg_hash_fetch_all_installed(&conf->pkg_hash, installed);
+         for (i = 0; i < installed->len; i++) {
+              pkg = installed->pkgs[i];
+              opkg_upgrade_pkg(conf, pkg);
+         }
+         pkg_vec_free(installed);
+     }
+
+     /* recheck to verify that all dependences are satisfied */
+     if (0) opkg_satisfy_all_dependences(conf);
+
+     opkg_configure_packages(conf, NULL);
+
+     write_status_files_if_changed(conf);
+
+     return 0;
+}
+
+static int opkg_download_cmd(opkg_conf_t *conf, int argc, char **argv)
+{
+     int i, err;
+     char *arg;
+     pkg_t *pkg;
+
+     pkg_info_preinstall_check(conf);
+     for (i = 0; i < argc; i++) {
+         arg = argv[i];
+
+         pkg = pkg_hash_fetch_best_installation_candidate_by_name(conf, arg);
+         if (pkg == NULL) {
+              opkg_message(conf, OPKG_ERROR,
+                           "Cannot find package %s.\n"
+                           "Check the spelling or perhaps run 'opkg update'\n",
+                           arg);
+              continue;
+         }
+
+         err = opkg_download_pkg(conf, pkg, ".");
+
+         if (err) {
+              opkg_message(conf, OPKG_ERROR,
+                           "Failed to download %s\n", pkg->name);
+         } else {
+              opkg_message(conf, OPKG_NOTICE,
+                           "Downloaded %s as %s\n",
+                           pkg->name, pkg->local_filename);
+         }
+     }
+
+     return 0;
+}
+
+
+static int opkg_list_cmd(opkg_conf_t *conf, int argc, char **argv)
+{
+     int i ;
+     pkg_vec_t *available;
+     pkg_t *pkg;
+     char desc_short[OPKG_LIST_DESCRIPTION_LENGTH];
+     char *newline;
+     char *pkg_name = NULL;
+     char *version_str;
+
+     if (argc > 0) {
+         pkg_name = argv[0];
+     }
+     available = pkg_vec_alloc();
+     pkg_hash_fetch_available(&conf->pkg_hash, available);
+     for (i=0; i < available->len; i++) {
+         pkg = available->pkgs[i];
+         /* if we have package name or pattern and pkg does not match, then skip it */
+         if (pkg_name && fnmatch(pkg_name, pkg->name, 0)) 
+              continue;
+         if (pkg->description) {
+              strncpy(desc_short, pkg->description, OPKG_LIST_DESCRIPTION_LENGTH);
+         } else {
+              desc_short[0] = '\0';
+         }
+         desc_short[OPKG_LIST_DESCRIPTION_LENGTH - 1] = '\0';
+         newline = strchr(desc_short, '\n');
+         if (newline) {
+              *newline = '\0';
+         }
+#ifndef OPKG_LIB
+         printf("%s - %s\n", pkg->name, desc_short);
+#else
+         if (opkg_cb_list) {
+               version_str = pkg_version_str_alloc(pkg);
+               opkg_cb_list(pkg->name,desc_short,
+                                            version_str,
+                                        pkg->state_status,
+                                        p_userdata);
+               free(version_str);
+         }
+#endif
+     }
+     pkg_vec_free(available);
+
+     return 0;
+}
+
+
+static int opkg_list_installed_cmd(opkg_conf_t *conf, int argc, char **argv)
+{
+     int i ;
+     pkg_vec_t *available;
+     pkg_t *pkg;
+     char desc_short[OPKG_LIST_DESCRIPTION_LENGTH];
+     char *newline;
+     char *pkg_name = NULL;
+     char *version_str;
+
+     if (argc > 0) {
+         pkg_name = argv[0];
+     }
+     available = pkg_vec_alloc();
+     pkg_hash_fetch_all_installed(&conf->pkg_hash, available);
+     for (i=0; i < available->len; i++) {
+         pkg = available->pkgs[i];
+         /* if we have package name or pattern and pkg does not match, then skip it */
+         if (pkg_name && fnmatch(pkg_name, pkg->name, 0)) 
+              continue;
+         if (pkg->description) {
+              strncpy(desc_short, pkg->description, OPKG_LIST_DESCRIPTION_LENGTH);
+         } else {
+              desc_short[0] = '\0';
+         }
+         desc_short[OPKG_LIST_DESCRIPTION_LENGTH - 1] = '\0';
+         newline = strchr(desc_short, '\n');
+         if (newline) {
+              *newline = '\0';
+         }
+#ifndef OPKG_LIB
+         printf("%s - %s\n", pkg->name, desc_short);
+#else
+         if (opkg_cb_list) {
+               version_str = pkg_version_str_alloc(pkg);
+               opkg_cb_list(pkg->name,desc_short,
+                                            version_str,
+                                        pkg->state_status,
+                                        p_userdata);
+               free(version_str);
+         }
+#endif
+     }
+
+     return 0;
+}
+
+static int opkg_info_status_cmd(opkg_conf_t *conf, int argc, char **argv, int installed_only)
+{
+     int i;
+     pkg_vec_t *available;
+     pkg_t *pkg;
+     char *pkg_name = NULL;
+     char **pkg_fields = NULL;
+     int n_fields = 0;
+     char *buff ; // = (char *)malloc(1);
+
+     if (argc > 0) {
+         pkg_name = argv[0];
+     }
+     if (argc > 1) {
+         pkg_fields = &argv[1];
+         n_fields = argc - 1;
+     }
+
+     available = pkg_vec_alloc();
+     if (installed_only)
+         pkg_hash_fetch_all_installed(&conf->pkg_hash, available);
+     else
+         pkg_hash_fetch_available(&conf->pkg_hash, available);
+     for (i=0; i < available->len; i++) {
+         pkg = available->pkgs[i];
+         if (pkg_name && fnmatch(pkg_name, pkg->name, 0)) {
+              continue;
+         }
+#ifndef OPKG_LIB
+         if (n_fields) {
+              for (j = 0; j < n_fields; j++)
+                   pkg_print_field(pkg, stdout, pkg_fields[j]);
+         } else {
+              pkg_print_info(pkg, stdout);
+         }
+#else
+
+         buff = pkg_formatted_info(pkg);
+          if ( buff ) {
+              if (opkg_cb_status) opkg_cb_status(pkg->name,
+                                                 pkg->state_status,
+                                                 buff,
+                                                 p_userdata);
+/* 
+   We should not forget that actually the pointer is allocated. 
+   We need to free it :)  ( Thanks florian for seeing the error )
+*/
+               free(buff);
+          }
+#endif
+         if (conf->verbosity > 1) {
+              conffile_list_elt_t *iter;
+              for (iter = pkg->conffiles.head; iter; iter = iter->next) {
+                   conffile_t *cf = iter->data;
+                   int modified = conffile_has_been_modified(conf, cf);
+                   opkg_message(conf, OPKG_NOTICE, "conffile=%s md5sum=%s modified=%d\n",
+                                cf->name, cf->value, modified);
+              }
+         }
+     }
+#ifndef OPKG_LIB
+     if (buff)
+         free(buff);
+#endif
+     pkg_vec_free(available);
+
+     return 0;
+}
+
+static int opkg_info_cmd(opkg_conf_t *conf, int argc, char **argv)
+{
+     return opkg_info_status_cmd(conf, argc, argv, 0);
+}
+
+static int opkg_status_cmd(opkg_conf_t *conf, int argc, char **argv)
+{
+     return opkg_info_status_cmd(conf, argc, argv, 1);
+}
+
+static int opkg_configure_cmd(opkg_conf_t *conf, int argc, char **argv)
+{
+     
+     int err;
+     if (argc > 0) {
+         char *pkg_name = NULL;
+
+         pkg_name = argv[0];
+
+         err = opkg_configure_packages (conf, pkg_name);
+     
+     } else {
+         err = opkg_configure_packages (conf, NULL);
+     }
+
+     write_status_files_if_changed(conf);
+
+     return err;
+}
+
+static int opkg_install_pending_cmd(opkg_conf_t *conf, int argc, char **argv)
+{
+     int i, err;
+     char *globpattern;
+     glob_t globbuf;
+    
+     sprintf_alloc(&globpattern, "%s/*" OPKG_PKG_EXTENSION, conf->pending_dir);
+     err = glob(globpattern, 0, NULL, &globbuf);
+     free(globpattern);
+     if (err) {
+         return 0;
+     }
+
+     opkg_message(conf, OPKG_NOTICE,
+                 "The following packages in %s will now be installed.\n",
+                 conf->pending_dir);
+     for (i = 0; i < globbuf.gl_pathc; i++) {
+         opkg_message(conf, OPKG_NOTICE,
+                      "%s%s", i == 0 ? "" : " ", globbuf.gl_pathv[i]);
+     }
+     opkg_message(conf, OPKG_NOTICE, "\n");
+     for (i = 0; i < globbuf.gl_pathc; i++) {
+         err = opkg_install_from_file(conf, globbuf.gl_pathv[i]);
+         if (err == 0) {
+              err = unlink(globbuf.gl_pathv[i]);
+              if (err) {
+                   opkg_message(conf, OPKG_ERROR,
+                                "%s: ERROR: failed to unlink %s: %s\n",
+                                __FUNCTION__, globbuf.gl_pathv[i], strerror(err));
+                   return err;
+              }
+         }
+     }
+     globfree(&globbuf);
+
+     return err;
+}
+
+static int opkg_remove_cmd(opkg_conf_t *conf, int argc, char **argv)
+{
+     int i,a,done;
+     pkg_t *pkg;
+     pkg_t *pkg_to_remove;
+     pkg_vec_t *available;
+     char *pkg_name = NULL;
+     global_conf = conf;
+     signal(SIGINT, sigint_handler);
+
+// ENH: Add the "no pkg removed" just in case.
+
+    done = 0;
+
+     available = pkg_vec_alloc();
+     pkg_info_preinstall_check(conf);
+     if ( argc > 0 ) {
+        pkg_hash_fetch_all_installed(&conf->pkg_hash, available);
+        for (i=0; i < argc; i++) {
+           pkg_name = malloc(strlen(argv[i])+2);
+           strcpy(pkg_name,argv[i]);
+           for (a=0; a < available->len; a++) {
+               pkg = available->pkgs[a];
+              if (pkg_name && fnmatch(pkg_name, pkg->name, 0)) {
+                  continue;
+               }
+               if (conf->restrict_to_default_dest) {
+                   pkg_to_remove = pkg_hash_fetch_installed_by_name_dest(&conf->pkg_hash,
+                                                               pkg->name,
+                                                               conf->default_dest);
+               } else {
+                   pkg_to_remove = pkg_hash_fetch_installed_by_name(&conf->pkg_hash, pkg->name );
+               }
+        
+               if (pkg == NULL) {
+                   opkg_message(conf, OPKG_ERROR, "Package %s is not installed.\n", pkg->name);
+                   continue;
+               }
+               if (pkg->state_status == SS_NOT_INSTALLED) {    // Added the control, so every already removed package could be skipped
+                   opkg_message(conf, OPKG_ERROR, "Package seems to be %s not installed (STATUS = NOT_INSTALLED).\n", pkg->name);
+                    continue;
+               }
+               opkg_remove_pkg(conf, pkg_to_remove,0);
+               done = 1;
+           }
+           free (pkg_name);
+        }
+        pkg_vec_free(available);
+     } else {
+         pkg_vec_t *installed_pkgs = pkg_vec_alloc();
+         int i;
+         int flagged_pkg_count = 0;
+         int removed;
+
+         pkg_hash_fetch_all_installed(&conf->pkg_hash, installed_pkgs);
+
+         for (i = 0; i < installed_pkgs->len; i++) {
+              pkg_t *pkg = installed_pkgs->pkgs[i];
+              if (pkg->state_flag & SF_USER) {
+                   flagged_pkg_count++;
+              } else {
+                   if (!pkg_has_installed_dependents(conf, pkg->parent, pkg, NULL))
+                        opkg_message(conf, OPKG_NOTICE, "Non-user leaf package: %s\n", pkg->name);
+              }
+         }
+         if (!flagged_pkg_count) {
+              opkg_message(conf, OPKG_NOTICE, "No packages flagged as installed by user, \n"
+                           "so refusing to uninstall unflagged non-leaf packages\n");
+              return 0;
+         }
+
+         /* find packages not flagged SF_USER (i.e., installed to
+          * satisfy a dependence) and not having any dependents, and
+          * remove them */
+         do {
+              removed = 0;
+              for (i = 0; i < installed_pkgs->len; i++) {
+                   pkg_t *pkg = installed_pkgs->pkgs[i];
+                   if (!(pkg->state_flag & SF_USER)
+                       && !pkg_has_installed_dependents(conf, pkg->parent, pkg, NULL)) {
+                        removed++;
+                        opkg_message(conf, OPKG_NOTICE, "Removing non-user leaf package %s\n");
+                        opkg_remove_pkg(conf, pkg,0);
+                         done = 1;
+                   }
+              }
+         } while (removed);
+         pkg_vec_free(installed_pkgs);
+     }
+
+     if ( done == 0 ) 
+        opkg_message(conf, OPKG_NOTICE, "No packages removed.\n");
+
+     write_status_files_if_changed(conf);
+     return 0;
+}
+
+static int opkg_purge_cmd(opkg_conf_t *conf, int argc, char **argv)
+{
+     int i;
+     pkg_t *pkg;
+
+     global_conf = conf;
+     signal(SIGINT, sigint_handler);
+
+     pkg_info_preinstall_check(conf);
+
+     for (i=0; i < argc; i++) {
+         if (conf->restrict_to_default_dest) {
+              pkg = pkg_hash_fetch_installed_by_name_dest(&conf->pkg_hash,
+                                                          argv[i],
+                                                          conf->default_dest);
+         } else {
+              pkg = pkg_hash_fetch_installed_by_name(&conf->pkg_hash, argv[i]);
+         }
+
+         if (pkg == NULL) {
+              opkg_message(conf, OPKG_ERROR,
+                           "Package %s is not installed.\n", argv[i]);
+              continue;
+         }
+         opkg_purge_pkg(conf, pkg);
+     }
+
+     write_status_files_if_changed(conf);
+     return 0;
+}
+
+static int opkg_flag_cmd(opkg_conf_t *conf, int argc, char **argv)
+{
+     int i;
+     pkg_t *pkg;
+     const char *flags = argv[0];
+    
+     global_conf = conf;
+     signal(SIGINT, sigint_handler);
+
+     for (i=1; i < argc; i++) {
+         if (conf->restrict_to_default_dest) {
+              pkg = pkg_hash_fetch_installed_by_name_dest(&conf->pkg_hash,
+                                                          argv[i],
+                                                          conf->default_dest);
+         } else {
+              pkg = pkg_hash_fetch_installed_by_name(&conf->pkg_hash, argv[i]);
+         }
+
+         if (pkg == NULL) {
+              opkg_message(conf, OPKG_ERROR,
+                           "Package %s is not installed.\n", argv[i]);
+              continue;
+         }
+          if (( strcmp(flags,"hold")==0)||( strcmp(flags,"noprune")==0)||
+              ( strcmp(flags,"user")==0)||( strcmp(flags,"ok")==0)) {
+             pkg->state_flag = pkg_state_flag_from_str(flags);
+          }
+/* pb_ asked this feature 03292004 */
+/* Actually I will use only this two, but this is an open for various status */
+          if (( strcmp(flags,"installed")==0)||( strcmp(flags,"unpacked")==0)){
+             pkg->state_status = pkg_state_status_from_str(flags);
+          }
+         opkg_state_changed++;
+         opkg_message(conf, OPKG_NOTICE,
+                      "Setting flags for package %s to %s\n",
+                      pkg->name, flags);
+     }
+
+     write_status_files_if_changed(conf);
+     return 0;
+}
+
+static int opkg_files_cmd(opkg_conf_t *conf, int argc, char **argv)
+{
+     pkg_t *pkg;
+     str_list_t *installed_files;
+     str_list_elt_t *iter;
+     char *pkg_version;
+     size_t buff_len = 8192;
+     size_t used_len;
+     char *buff ;
+
+     buff = (char *)malloc(buff_len);
+     if ( buff == NULL ) {
+        fprintf( stderr,"%s: Unable to allocate memory \n",__FUNCTION__);
+        return ENOMEM;
+     }
+     if (argc < 1) {
+         return EINVAL;
+     }
+
+     pkg = pkg_hash_fetch_installed_by_name(&conf->pkg_hash,
+                                           argv[0]);
+     if (pkg == NULL) {
+         opkg_message(conf, OPKG_ERROR,
+                      "Package %s not installed.\n", argv[0]);
+         return 0;
+     }
+
+     installed_files = pkg_get_installed_files(pkg);
+     pkg_version = pkg_version_str_alloc(pkg);
+
+#ifndef OPKG_LIB
+     printf("Package %s (%s) is installed on %s and has the following files:\n",
+           pkg->name, pkg_version, pkg->dest->name);
+     for (iter = installed_files->head; iter; iter = iter->next) {
+         puts(iter->data);
+     }
+#else
+     if (buff) {
+     try_again:
+         used_len = snprintf(buff, buff_len, "Package %s (%s) is installed on %s and has the following files:\n",
+                             pkg->name, pkg_version, pkg->dest->name) + 1;
+         if (used_len > buff_len) {
+              buff_len *= 2;
+              buff = realloc (buff, buff_len);
+              goto try_again;
+         }
+         for (iter = installed_files->head; iter; iter = iter->next) {
+              used_len += strlen (iter->data) + 1;
+              while (buff_len <= used_len) {
+                   buff_len *= 2;
+                   buff = realloc (buff, buff_len);
+              }
+              strncat(buff, iter->data, buff_len);
+              strncat(buff, "\n", buff_len);
+         } 
+         if (opkg_cb_list) opkg_cb_list(pkg->name,
+                                        buff,
+                                        pkg_version_str_alloc(pkg),
+                                        pkg->state_status,
+                                        p_userdata);
+         free(buff);
+     }
+#endif
+
+     free(pkg_version);
+     pkg_free_installed_files(pkg);
+
+     return 0;
+}
+
+static int opkg_depends_cmd(opkg_conf_t *conf, int argc, char **argv)
+{
+
+     if (argc > 0) {
+         pkg_vec_t *available_pkgs = pkg_vec_alloc();
+         const char *rel_str = "depends on";
+         int i;
+     
+         pkg_info_preinstall_check(conf);
+
+         if (conf->query_all)
+              pkg_hash_fetch_available(&conf->pkg_hash, available_pkgs);
+         else
+              pkg_hash_fetch_all_installed(&conf->pkg_hash, available_pkgs);
+         for (i = 0; i < argc; i++) {
+              const char *target = argv[i];
+              int j;
+
+              opkg_message(conf, OPKG_ERROR, "target=%s\n", target);
+
+              for (j = 0; j < available_pkgs->len; j++) {
+                   pkg_t *pkg = available_pkgs->pkgs[j];
+                   if (fnmatch(target, pkg->name, 0) == 0) {
+                        int k;
+                        int count = pkg->depends_count + pkg->pre_depends_count;
+                        opkg_message(conf, OPKG_ERROR, "What %s (arch=%s) %s\n",
+                                     target, pkg->architecture, rel_str);
+                        for (k = 0; k < count; k++) {
+                             compound_depend_t *cdepend = &pkg->depends[k];
+                             int l;
+                             for (l = 0; l < cdepend->possibility_count; l++) {
+                                  depend_t *possibility = cdepend->possibilities[l];
+                                  opkg_message(conf, OPKG_ERROR, "    %s", possibility->pkg->name);
+                                  if (conf->verbosity > 0) {
+                                       // char *ver = abstract_pkg_version_str_alloc(possibility->pkg); 
+                                       opkg_message(conf, OPKG_NOTICE, " %s", possibility->version);
+                                       if (possibility->version) {
+                                            char *typestr = NULL;
+                                            switch (possibility->constraint) {
+                                            case NONE: typestr = "none"; break;
+                                            case EARLIER: typestr = "<"; break;
+                                            case EARLIER_EQUAL: typestr = "<="; break;
+                                            case EQUAL: typestr = "="; break;
+                                            case LATER_EQUAL: typestr = ">="; break;
+                                            case LATER: typestr = ">"; break;
+                                            }
+                                            opkg_message(conf, OPKG_NOTICE, " (%s %s)", typestr, possibility->version);
+                                       }
+                                       // free(ver);
+                                  }
+                                  opkg_message(conf, OPKG_ERROR, "\n");
+                             }
+                        }
+                   }
+              }
+         }
+         pkg_vec_free(available_pkgs);
+     }
+     return 0;
+}
+
+enum what_field_type {
+  WHATDEPENDS,
+  WHATCONFLICTS,
+  WHATPROVIDES,
+  WHATREPLACES,
+  WHATRECOMMENDS,
+  WHATSUGGESTS
+};
+
+static int opkg_what_depends_conflicts_cmd(opkg_conf_t *conf, enum what_field_type what_field_type, int recursive, int argc, char **argv)
+{
+
+     if (argc > 0) {
+         pkg_vec_t *available_pkgs = pkg_vec_alloc();
+         const char *rel_str = NULL;
+         int i;
+         int changed;
+
+         switch (what_field_type) {
+         case WHATDEPENDS: rel_str = "depends on"; break;
+         case WHATCONFLICTS: rel_str = "conflicts with"; break;
+         case WHATSUGGESTS: rel_str = "suggests"; break;
+         case WHATRECOMMENDS: rel_str = "recommends"; break;
+         case WHATPROVIDES: rel_str = "provides"; break;
+         case WHATREPLACES: rel_str = "replaces"; break;
+         }
+     
+         if (conf->query_all)
+              pkg_hash_fetch_available(&conf->pkg_hash, available_pkgs);
+         else
+              pkg_hash_fetch_all_installed(&conf->pkg_hash, available_pkgs);
+
+         /* mark the root set */
+         pkg_vec_clear_marks(available_pkgs);
+         opkg_message(conf, OPKG_NOTICE, "Root set:\n");
+         for (i = 0; i < argc; i++) {
+              const char *dependee_pattern = argv[i];
+              pkg_vec_mark_if_matches(available_pkgs, dependee_pattern);
+         }
+         for (i = 0; i < available_pkgs->len; i++) {
+              pkg_t *pkg = available_pkgs->pkgs[i];
+              if (pkg->state_flag & SF_MARKED) {
+                   /* mark the parent (abstract) package */
+                   pkg_mark_provides(pkg);
+                   opkg_message(conf, OPKG_NOTICE, "  %s\n", pkg->name);
+              }
+         }
+
+         opkg_message(conf, OPKG_NOTICE, "What %s root set\n", rel_str);
+         do {
+              int j;
+              changed = 0;
+
+              for (j = 0; j < available_pkgs->len; j++) {
+                   pkg_t *pkg = available_pkgs->pkgs[j];
+                   int k;
+                   int count = ((what_field_type == WHATCONFLICTS)
+                                ? pkg->conflicts_count
+                                : pkg->pre_depends_count + pkg->depends_count + pkg->recommends_count + pkg->suggests_count);
+                   /* skip this package if it is already marked */
+                   if (pkg->parent->state_flag & SF_MARKED) {
+                        continue;
+                   }
+                   for (k = 0; k < count; k++) {
+                        compound_depend_t *cdepend = 
+                             (what_field_type == WHATCONFLICTS) ? &pkg->conflicts[k] : &pkg->depends[k];
+                        int l;
+                        for (l = 0; l < cdepend->possibility_count; l++) {
+                             depend_t *possibility = cdepend->possibilities[l];
+                             if (possibility->pkg->state_flag & SF_MARKED) {
+                                  /* mark the depending package so we won't visit it again */
+                                  pkg->state_flag |= SF_MARKED;
+                                  pkg_mark_provides(pkg);
+                                  changed++;
+
+                                  opkg_message(conf, OPKG_NOTICE, "    %s", pkg->name);
+                                  if (conf->verbosity > 0) {
+                                       char *ver = pkg_version_str_alloc(pkg); 
+                                       opkg_message(conf, OPKG_NOTICE, " %s", ver);
+                                       opkg_message(conf, OPKG_NOTICE, "\t%s %s", rel_str, possibility->pkg->name);
+                                       if (possibility->version) {
+                                            char *typestr = NULL;
+                                            switch (possibility->constraint) {
+                                            case NONE: typestr = "none"; break;
+                                            case EARLIER: typestr = "<"; break;
+                                            case EARLIER_EQUAL: typestr = "<="; break;
+                                            case EQUAL: typestr = "="; break;
+                                            case LATER_EQUAL: typestr = ">="; break;
+                                            case LATER: typestr = ">"; break;
+                                            }
+                                            opkg_message(conf, OPKG_NOTICE, " (%s %s)", typestr, possibility->version);
+                                       }
+                                       free(ver);
+                                       if (!pkg_dependence_satisfiable(conf, possibility))
+                                            opkg_message(conf, OPKG_NOTICE, " unsatisfiable");
+                                  }
+                                  opkg_message(conf, OPKG_NOTICE, "\n");
+                                  goto next_package;
+                             }
+                        }
+                   }
+              next_package:
+                   ;
+              }
+         } while (changed && recursive);
+         pkg_vec_free(available_pkgs);
+     }
+
+     return 0;
+}
+
+int pkg_mark_provides(pkg_t *pkg)
+{
+     int provides_count = pkg->provides_count;
+     abstract_pkg_t **provides = pkg->provides;
+     int i;
+     pkg->parent->state_flag |= SF_MARKED;
+     for (i = 0; i < provides_count; i++) {
+         provides[i]->state_flag |= SF_MARKED;
+     }
+     return 0;
+}
+
+static int opkg_whatdepends_recursively_cmd(opkg_conf_t *conf, int argc, char **argv)
+{
+     return opkg_what_depends_conflicts_cmd(conf, WHATDEPENDS, 1, argc, argv);
+}
+static int opkg_whatdepends_cmd(opkg_conf_t *conf, int argc, char **argv)
+{
+     return opkg_what_depends_conflicts_cmd(conf, WHATDEPENDS, 0, argc, argv);
+}
+
+static int opkg_whatsuggests_cmd(opkg_conf_t *conf, int argc, char **argv)
+{
+     return opkg_what_depends_conflicts_cmd(conf, WHATSUGGESTS, 0, argc, argv);
+}
+
+static int opkg_whatrecommends_cmd(opkg_conf_t *conf, int argc, char **argv)
+{
+     return opkg_what_depends_conflicts_cmd(conf, WHATRECOMMENDS, 0, argc, argv);
+}
+
+static int opkg_whatconflicts_cmd(opkg_conf_t *conf, int argc, char **argv)
+{
+     return opkg_what_depends_conflicts_cmd(conf, WHATCONFLICTS, 0, argc, argv);
+}
+
+static int opkg_what_provides_replaces_cmd(opkg_conf_t *conf, enum what_field_type what_field_type, int argc, char **argv)
+{
+
+     if (argc > 0) {
+         pkg_vec_t *available_pkgs = pkg_vec_alloc();
+         const char *rel_str = (what_field_type == WHATPROVIDES ? "provides" : "replaces");
+         int i;
+     
+         pkg_info_preinstall_check(conf);
+
+         if (conf->query_all)
+              pkg_hash_fetch_available(&conf->pkg_hash, available_pkgs);
+         else
+              pkg_hash_fetch_all_installed(&conf->pkg_hash, available_pkgs);
+         for (i = 0; i < argc; i++) {
+              const char *target = argv[i];
+              int j;
+
+              opkg_message(conf, OPKG_ERROR, "What %s %s\n",
+                           rel_str, target);
+              for (j = 0; j < available_pkgs->len; j++) {
+                   pkg_t *pkg = available_pkgs->pkgs[j];
+                   int k;
+                   int count = (what_field_type == WHATPROVIDES) ? pkg->provides_count : pkg->replaces_count;
+                   for (k = 0; k < count; k++) {
+                        abstract_pkg_t *apkg = 
+                             ((what_field_type == WHATPROVIDES) 
+                              ? pkg->provides[k]
+                              : pkg->replaces[k]);
+                        if (fnmatch(target, apkg->name, 0) == 0) {
+                             opkg_message(conf, OPKG_ERROR, "    %s", pkg->name);
+                             if (strcmp(target, apkg->name) != 0)
+                                  opkg_message(conf, OPKG_ERROR, "\t%s %s\n", rel_str, apkg->name);
+                             opkg_message(conf, OPKG_ERROR, "\n");
+                        }
+                   }
+              }
+         }
+         pkg_vec_free(available_pkgs);
+     }
+     return 0;
+}
+
+static int opkg_whatprovides_cmd(opkg_conf_t *conf, int argc, char **argv)
+{
+     return opkg_what_provides_replaces_cmd(conf, WHATPROVIDES, argc, argv);
+}
+
+static int opkg_whatreplaces_cmd(opkg_conf_t *conf, int argc, char **argv)
+{
+     return opkg_what_provides_replaces_cmd(conf, WHATREPLACES, argc, argv);
+}
+
+static int opkg_search_cmd(opkg_conf_t *conf, int argc, char **argv)
+{
+     int i;
+
+     pkg_vec_t *installed;
+     pkg_t *pkg;
+     str_list_t *installed_files;
+     str_list_elt_t *iter;
+     char *installed_file;
+
+     if (argc < 1) {
+         return EINVAL;
+     }
+     installed = pkg_vec_alloc();
+     pkg_hash_fetch_all_installed(&conf->pkg_hash, installed);
+
+     for (i=0; i < installed->len; i++) {
+         pkg = installed->pkgs[i];
+
+         installed_files = pkg_get_installed_files(pkg);
+
+         for (iter = installed_files->head; iter; iter = iter->next) {
+              installed_file = iter->data;
+              if (fnmatch(argv[0], installed_file, 0)==0)  {
+#ifndef OPKG_LIB
+                   printf("%s: %s\n", pkg->name, installed_file);
+#else
+                       if (opkg_cb_list) opkg_cb_list(pkg->name, 
+                                                      installed_file, 
+                                                      pkg_version_str_alloc(pkg), 
+                                                      pkg->state_status, p_userdata);
+#endif                    
+              }                
+         }
+
+         pkg_free_installed_files(pkg);
+     }
+
+     /* XXX: CLEANUP: It's not obvious from the name of
+       pkg_hash_fetch_all_installed that we need to call
+       pkg_vec_free to avoid a memory leak. */
+     pkg_vec_free(installed);
+
+     return 0;
+}
+
+static int opkg_compare_versions_cmd(opkg_conf_t *conf, int argc, char **argv)
+{
+     if (argc == 3) {
+         /* this is a bit gross */
+         struct pkg p1, p2;
+         parseVersion(&p1, argv[0]); 
+         parseVersion(&p2, argv[2]); 
+         return pkg_version_satisfied(&p1, &p2, argv[1]);
+     } else {
+         opkg_message(conf, OPKG_ERROR,
+                      "opkg compare_versions <v1> <op> <v2>\n"
+                      "<op> is one of <= >= << >> =\n");
+         return -1;
+     }
+}
+
+#ifndef HOST_CPU_STR
+#define HOST_CPU_STR__(X) #X
+#define HOST_CPU_STR_(X) HOST_CPU_STR__(X)
+#define HOST_CPU_STR HOST_CPU_STR_(HOST_CPU_FOO)
+#endif
+
+static int opkg_print_architecture_cmd(opkg_conf_t *conf, int argc, char **argv)
+{
+     nv_pair_list_elt_t *l;
+
+     l = conf->arch_list.head;
+     while (l) {
+         nv_pair_t *nv = l->data;
+         printf("arch %s %s\n", nv->name, nv->value);
+         l = l->next;
+     }
+     return 0;
+}
+
+
diff --git a/libopkg/opkg_cmd.h b/libopkg/opkg_cmd.h
new file mode 100644 (file)
index 0000000..157e929
--- /dev/null
@@ -0,0 +1,46 @@
+/* opkg_cmd.h - the itsy package management system
+
+   Carl D. Worth
+
+   Copyright (C) 2001 University of Southern California
+
+   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, 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
+   General Public License for more details.
+*/
+
+#ifndef OPKG_CMD_H
+#define OPKG_CMD_H
+
+typedef int (*opkg_cmd_fun_t)(opkg_conf_t *conf, int argc, const char **argv);
+
+struct opkg_cmd
+{
+    char *name;
+    int requires_args;
+    opkg_cmd_fun_t fun;
+};
+typedef struct opkg_cmd opkg_cmd_t;
+
+opkg_cmd_t *opkg_cmd_find(const char *name);
+#ifdef OPKG_LIB
+int opkg_cmd_exec(opkg_cmd_t *cmd, opkg_conf_t *conf, int argc, 
+                  const char **argv, void *userdata);
+#else
+int opkg_cmd_exec(opkg_cmd_t *cmd, opkg_conf_t *conf, int argc, const char **argv);
+#endif
+int opkg_multiple_files_scan (opkg_conf_t *conf, int argc, char *argv[]);
+/* install any packges with state_want == SW_INSTALL */
+int opkg_install_wanted_packages(opkg_conf_t *conf);
+/* ensure that all dependences are satisfied */
+int opkg_configure_packages(opkg_conf_t *conf, char *pkg_name);
+
+int pkg_mark_provides(pkg_t *pkg);
+
+#endif
diff --git a/libopkg/opkg_conf.c b/libopkg/opkg_conf.c
new file mode 100644 (file)
index 0000000..abeab19
--- /dev/null
@@ -0,0 +1,717 @@
+/* opkg_conf.c - the itsy package management system
+
+   Carl D. Worth
+
+   Copyright (C) 2001 University of Southern California
+
+   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, 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
+   General Public License for more details.
+*/
+
+#include <glob.h>
+
+#include "opkg.h"
+#include "opkg_conf.h"
+
+#include "xregex.h"
+#include "sprintf_alloc.h"
+#include "opkg_conf.h"
+#include "opkg_message.h"
+#include "file_util.h"
+#include "str_util.h"
+#include "xsystem.h"
+
+static int opkg_conf_parse_file(opkg_conf_t *conf, const char *filename,
+                               pkg_src_list_t *pkg_src_list,
+                               nv_pair_list_t *tmp_dest_nv_pair_list,
+                               char **tmp_lists_dir);
+static int opkg_init_options_array(const opkg_conf_t *conf, opkg_option_t **options);
+static int opkg_conf_set_option(const opkg_option_t *options,
+                               const char *name, const char *value);
+static int opkg_conf_set_default_dest(opkg_conf_t *conf,
+                                     const char *default_dest_name);
+static int set_and_load_pkg_src_list(opkg_conf_t *conf,
+                                    pkg_src_list_t *nv_pair_list);
+static int set_and_load_pkg_dest_list(opkg_conf_t *conf,
+                                     nv_pair_list_t *nv_pair_list, char * lists_dir);
+
+int opkg_init_options_array(const opkg_conf_t *conf, opkg_option_t **options)
+{
+     opkg_option_t tmp[] = {
+         { "force_defaults", OPKG_OPT_TYPE_BOOL, &conf->force_defaults },
+         { "force_depends", OPKG_OPT_TYPE_BOOL, &conf->force_depends },
+         { "force_overwrite", OPKG_OPT_TYPE_BOOL, &conf->force_overwrite },
+         { "force_downgrade", OPKG_OPT_TYPE_BOOL, &conf->force_downgrade },
+         { "force_reinstall", OPKG_OPT_TYPE_BOOL, &conf->force_reinstall },
+         { "force_space", OPKG_OPT_TYPE_BOOL, &conf->force_space },
+         { "ftp_proxy", OPKG_OPT_TYPE_STRING, &conf->ftp_proxy },
+         { "http_proxy", OPKG_OPT_TYPE_STRING, &conf->http_proxy },
+         { "multiple_providers", OPKG_OPT_TYPE_BOOL, &conf->multiple_providers },
+         { "no_proxy", OPKG_OPT_TYPE_STRING, &conf->no_proxy },
+         { "test", OPKG_OPT_TYPE_INT, &conf->noaction },
+         { "noaction", OPKG_OPT_TYPE_INT, &conf->noaction },
+         { "nodeps", OPKG_OPT_TYPE_BOOL, &conf->nodeps },
+         { "offline_root", OPKG_OPT_TYPE_STRING, &conf->offline_root },
+         { "offline_root_post_script_cmd", OPKG_OPT_TYPE_STRING, &conf->offline_root_post_script_cmd },
+         { "offline_root_pre_script_cmd", OPKG_OPT_TYPE_STRING, &conf->offline_root_pre_script_cmd },
+         { "proxy_passwd", OPKG_OPT_TYPE_STRING, &conf->proxy_passwd },
+         { "proxy_user", OPKG_OPT_TYPE_STRING, &conf->proxy_user },
+         { "query-all", OPKG_OPT_TYPE_BOOL, &conf->query_all },
+         { "verbose-wget", OPKG_OPT_TYPE_BOOL, &conf->verbose_wget },
+         { "verbosity", OPKG_OPT_TYPE_BOOL, &conf->verbosity },
+         { NULL }
+     };
+
+     *options = (opkg_option_t *)malloc(sizeof(tmp));
+     if ( options == NULL ){
+        fprintf(stderr,"%s: Unable to allocate memory\n",__FUNCTION__);
+        return -1;
+     }
+
+     memcpy(*options, tmp, sizeof(tmp));
+     return 0;
+};
+
+static void opkg_conf_override_string(char **conf_str, char *arg_str) 
+{
+     if (arg_str) {
+         if (*conf_str) {
+              free(*conf_str);
+         }
+         *conf_str = strdup(arg_str);
+     }
+}
+
+static void opkg_conf_free_string(char **conf_str)
+{
+     if (*conf_str) {
+         free(*conf_str);
+         *conf_str = NULL;
+     }
+}
+
+int opkg_conf_init(opkg_conf_t *conf, const args_t *args)
+{
+     int err;
+     char *tmp_dir_base;
+     nv_pair_list_t tmp_dest_nv_pair_list;
+     char * lists_dir =NULL;
+     glob_t globbuf;
+     char *etc_opkg_conf_pattern = "/etc/opkg/*.conf";
+     char *pending_dir  =NULL;
+
+     memset(conf, 0, sizeof(opkg_conf_t));
+
+     pkg_src_list_init(&conf->pkg_src_list);
+
+     nv_pair_list_init(&tmp_dest_nv_pair_list);
+     pkg_dest_list_init(&conf->pkg_dest_list);
+
+     nv_pair_list_init(&conf->arch_list);
+
+     conf->restrict_to_default_dest = 0;
+     conf->default_dest = NULL;
+
+
+     if (args->tmp_dir)
+         tmp_dir_base = args->tmp_dir;
+     else 
+         tmp_dir_base = getenv("TMPDIR");
+     sprintf_alloc(&conf->tmp_dir, "%s/%s",
+                  tmp_dir_base ? tmp_dir_base : OPKG_CONF_DEFAULT_TMP_DIR_BASE,
+                  OPKG_CONF_TMP_DIR_SUFFIX);
+     conf->tmp_dir = mkdtemp(conf->tmp_dir);
+     if (conf->tmp_dir == NULL) {
+         fprintf(stderr, "%s: Failed to create temporary directory `%s': %s\n",
+                 __FUNCTION__, conf->tmp_dir, strerror(errno));
+         return errno;
+     }
+
+     conf->force_depends = 0;
+     conf->force_defaults = 0;
+     conf->force_overwrite = 0;
+     conf->force_downgrade = 0;
+     conf->force_reinstall = 0;
+     conf->force_space = 0;
+     conf->force_removal_of_essential_packages = 0;
+     conf->force_removal_of_dependent_packages = 0;
+     conf->nodeps = 0;
+     conf->verbose_wget = 0;
+     conf->offline_root = NULL;
+     conf->offline_root_pre_script_cmd = NULL;
+     conf->offline_root_post_script_cmd = NULL;
+     conf->multiple_providers = 0;
+     conf->verbosity = 1;
+     conf->noaction = 0;
+
+     conf->http_proxy = NULL;
+     conf->ftp_proxy = NULL;
+     conf->no_proxy = NULL;
+     conf->proxy_user = NULL;
+     conf->proxy_passwd = NULL;
+
+     pkg_hash_init("pkg-hash", &conf->pkg_hash, OPKG_CONF_DEFAULT_HASH_LEN);
+     hash_table_init("file-hash", &conf->file_hash, OPKG_CONF_DEFAULT_HASH_LEN);
+     hash_table_init("obs-file-hash", &conf->obs_file_hash, OPKG_CONF_DEFAULT_HASH_LEN);
+     lists_dir=(char *)malloc(1);
+     lists_dir[0]='\0';
+     if (args->conf_file) {
+         struct stat stat_buf;
+         err = stat(args->conf_file, &stat_buf);
+         if (err == 0)
+              if (opkg_conf_parse_file(conf, args->conf_file,
+                                   &conf->pkg_src_list, &tmp_dest_nv_pair_list,&lists_dir)<0) {
+                   /* Memory leakage from opkg_conf_parse-file */
+                   return -1;
+               }
+                   
+     }
+
+     /* if (!lists_dir ){*/
+     if (strlen(lists_dir)<=1 ){
+        lists_dir = realloc(lists_dir,strlen(OPKG_CONF_LISTS_DIR)+2);
+        sprintf (lists_dir,"%s",OPKG_CONF_LISTS_DIR);
+     }
+
+     if (args->offline_root) {
+            char *tmp = malloc(strlen(lists_dir) + strlen(args->offline_root) + 1);
+            sprintf_alloc(&tmp, "%s/%s",args->offline_root,lists_dir);
+            free(lists_dir);
+            lists_dir = tmp;
+     }
+
+     pending_dir = malloc(strlen(lists_dir)+strlen("/pending")+5);
+     snprintf(pending_dir,strlen(lists_dir)+strlen("/pending") ,"%s%s",lists_dir,"/pending");
+
+     conf->lists_dir = strdup(lists_dir);
+     conf->pending_dir = strdup(pending_dir);
+
+     if (args->offline_root) 
+         sprintf_alloc(&etc_opkg_conf_pattern, "%s/etc/opkg/*.conf", args->offline_root);
+     memset(&globbuf, 0, sizeof(globbuf));
+     err = glob(etc_opkg_conf_pattern, 0, NULL, &globbuf);
+     if (!err) {
+         int i;
+         for (i = 0; i < globbuf.gl_pathc; i++) {
+              if (globbuf.gl_pathv[i]) 
+                   if ( opkg_conf_parse_file(conf, globbuf.gl_pathv[i], 
+                                        &conf->pkg_src_list, &tmp_dest_nv_pair_list,&lists_dir)<0) {
+                        /* Memory leakage from opkg_conf_parse-file */
+                        return -1;
+                   }
+         }
+     }
+     globfree(&globbuf);
+
+     /* if no architectures were defined, then default all, noarch, and host architecture */
+     if (nv_pair_list_empty(&conf->arch_list)) {
+         nv_pair_list_append(&conf->arch_list, "all", "1");
+         nv_pair_list_append(&conf->arch_list, "noarch", "1");
+         nv_pair_list_append(&conf->arch_list, HOST_CPU_STR, "10");
+     }
+
+     /* Even if there is no conf file, we'll need at least one dest. */
+     if (tmp_dest_nv_pair_list.head == NULL) {
+         nv_pair_list_append(&tmp_dest_nv_pair_list,
+                             OPKG_CONF_DEFAULT_DEST_NAME,
+                             OPKG_CONF_DEFAULT_DEST_ROOT_DIR);
+     }
+
+     /* After parsing the file, set options from command-line, (so that
+       command-line arguments take precedence) */
+     /* XXX: CLEANUP: The interaction between args.c and opkg_conf.c
+       really needs to be cleaned up. There is so much duplication
+       right now it is ridiculous. Maybe opkg_conf_t should just save
+       a pointer to args_t (which could then not be freed), rather
+       than duplicating every field here? */
+     if (args->force_depends) {
+         conf->force_depends = 1;
+     }
+     if (args->force_defaults) {
+         conf->force_defaults = 1;
+     }
+     if (args->force_overwrite) {
+         conf->force_overwrite = 1;
+     }
+     if (args->force_downgrade) {
+         conf->force_downgrade = 1;
+     }
+     if (args->force_reinstall) {
+         conf->force_reinstall = 1;
+     }
+     if (args->force_removal_of_dependent_packages) {
+         conf->force_removal_of_dependent_packages = 1;
+     }
+     if (args->force_removal_of_essential_packages) {
+         conf->force_removal_of_essential_packages = 1;
+     }
+     if (args->nodeps) {
+         conf->nodeps = 1;
+     }
+     if (args->noaction) {
+         conf->noaction = 1;
+     }
+     if (args->query_all) {
+         conf->query_all = 1;
+     }
+     if (args->verbose_wget) {
+         conf->verbose_wget = 1;
+     }
+     if (args->multiple_providers) {
+         conf->multiple_providers = 1;
+     }
+     if (args->verbosity != conf->verbosity) {
+         conf->verbosity = args->verbosity;
+     } 
+
+     opkg_conf_override_string(&conf->offline_root, 
+                              args->offline_root);
+     opkg_conf_override_string(&conf->offline_root_pre_script_cmd, 
+                              args->offline_root_pre_script_cmd);
+     opkg_conf_override_string(&conf->offline_root_post_script_cmd, 
+                              args->offline_root_post_script_cmd);
+
+/* Pigi: added a flag to disable the checking of structures if the command does not need to 
+         read anything from there.
+*/
+     if ( !(args->nocheckfordirorfile)){
+        /* need to run load the source list before dest list -Jamey */
+        if ( !(args->noreadfeedsfile))
+           set_and_load_pkg_src_list(conf, &conf->pkg_src_list);
+   
+        /* Now that we have resolved conf->offline_root, we can commit to
+          the directory names for the dests and load in all the package
+          lists. */
+        set_and_load_pkg_dest_list(conf, &tmp_dest_nv_pair_list,lists_dir);
+   
+        if (args->dest) {
+            err = opkg_conf_set_default_dest(conf, args->dest);
+            if (err) {
+                 return err;
+            }
+        }
+     }
+     nv_pair_list_deinit(&tmp_dest_nv_pair_list);
+     free(lists_dir);
+     free(pending_dir);
+
+     return 0;
+}
+
+void opkg_conf_deinit(opkg_conf_t *conf)
+{
+#ifdef OPKG_DEBUG_NO_TMP_CLEANUP
+#error
+     fprintf(stderr, "%s: Not cleaning up %s since opkg compiled "
+            "with OPKG_DEBUG_NO_TMP_CLEANUP\n",
+            __FUNCTION__, conf->tmp_dir);
+#else
+     int err;
+
+     err = rmdir(conf->tmp_dir);
+     if (err) {
+         if (errno == ENOTEMPTY) {
+              char *cmd;
+              sprintf_alloc(&cmd, "rm -fr %s\n", conf->tmp_dir);
+              err = xsystem(cmd);
+              free(cmd);
+         }
+         if (err)
+              fprintf(stderr, "WARNING: Unable to remove temporary directory: %s: %s\n", conf->tmp_dir, strerror(errno));
+     }
+#endif /* OPKG_DEBUG_NO_TMP_CLEANUP */
+
+     free(conf->tmp_dir); /*XXX*/
+
+     pkg_src_list_deinit(&conf->pkg_src_list);
+     pkg_dest_list_deinit(&conf->pkg_dest_list);
+     nv_pair_list_deinit(&conf->arch_list);
+     if (&conf->pkg_hash)
+                   pkg_hash_deinit(&conf->pkg_hash);
+     if (&conf->file_hash)
+                   hash_table_deinit(&conf->file_hash);
+     if (&conf->obs_file_hash)
+                   hash_table_deinit(&conf->obs_file_hash);
+
+     opkg_conf_free_string(&conf->offline_root);
+     opkg_conf_free_string(&conf->offline_root_pre_script_cmd);
+     opkg_conf_free_string(&conf->offline_root_post_script_cmd);
+
+     if (conf->verbosity > 1) { 
+         int i;
+         hash_table_t *hashes[] = {
+              &conf->pkg_hash,
+              &conf->file_hash,
+              &conf->obs_file_hash };
+         for (i = 0; i < 3; i++) {
+              hash_table_t *hash = hashes[i];
+              int c = 0;
+              int n_conflicts = 0;
+              int j;
+              for (j = 0; j < hash->n_entries; j++) {
+                   int len = 0;
+                   hash_entry_t *e = &hash->entries[j];
+                   if (e->next)
+                        n_conflicts++;
+                   while (e && e->key) {
+                        len++;
+                        e = e->next;
+                   }
+                   if (len > c) 
+                        c = len;
+              }
+              opkg_message(conf, OPKG_DEBUG, "hash_table[%s] n_buckets=%d n_elements=%d max_conflicts=%d n_conflicts=%d\n", 
+                           hash->name, hash->n_entries, hash->n_elements, c, n_conflicts);
+              hash_table_deinit(hash);
+         }
+     }
+}
+
+static int opkg_conf_set_default_dest(opkg_conf_t *conf,
+                                     const char *default_dest_name)
+{
+     pkg_dest_list_elt_t *iter;
+     pkg_dest_t *dest;
+
+     for (iter = conf->pkg_dest_list.head; iter; iter = iter->next) {
+         dest = iter->data;
+         if (strcmp(dest->name, default_dest_name) == 0) {
+              conf->default_dest = dest;
+              conf->restrict_to_default_dest = 1;
+              return 0;
+         }
+     }
+
+     fprintf(stderr, "ERROR: Unknown dest name: `%s'\n", default_dest_name);
+
+     return 1;
+}
+
+static int set_and_load_pkg_src_list(opkg_conf_t *conf, pkg_src_list_t *pkg_src_list)
+{
+     pkg_src_list_elt_t *iter;
+     pkg_src_t *src;
+     char *list_file;
+
+     for (iter = pkg_src_list->head; iter; iter = iter->next) {
+          src = iter->data;
+         if (src == NULL) {
+              continue;
+         }
+
+         sprintf_alloc(&list_file, "%s/%s", 
+                         conf->restrict_to_default_dest ? conf->default_dest->lists_dir : conf->lists_dir, 
+                         src->name);
+
+         if (file_exists(list_file)) {
+              pkg_hash_add_from_file(conf, list_file, src, NULL, 0);
+         }
+         free(list_file);
+     }
+
+     return 0;
+}
+
+static int set_and_load_pkg_dest_list(opkg_conf_t *conf, nv_pair_list_t *nv_pair_list, char *lists_dir )
+{
+     nv_pair_list_elt_t *iter;
+     nv_pair_t *nv_pair;
+     pkg_dest_t *dest;
+     char *root_dir;
+
+     for (iter = nv_pair_list->head; iter; iter = iter->next) {
+         nv_pair = iter->data;
+
+         if (conf->offline_root) {
+              sprintf_alloc(&root_dir, "%s%s", conf->offline_root, nv_pair->value);
+         } else {
+              root_dir = strdup(nv_pair->value);
+         }
+         dest = pkg_dest_list_append(&conf->pkg_dest_list, nv_pair->name, root_dir, lists_dir);
+         free(root_dir);
+         if (dest == NULL) {
+              continue;
+         }
+         if (conf->default_dest == NULL) {
+              conf->default_dest = dest;
+         }
+         if (file_exists(dest->status_file_name)) {
+              pkg_hash_add_from_file(conf, dest->status_file_name,
+                                     NULL, dest, 1);
+         }
+     }
+
+     return 0;
+}
+
+static int opkg_conf_parse_file(opkg_conf_t *conf, const char *filename,
+                               pkg_src_list_t *pkg_src_list,
+                               nv_pair_list_t *tmp_dest_nv_pair_list,
+                               char **lists_dir)
+{
+     int err;
+     opkg_option_t * options;
+     FILE *file = fopen(filename, "r");
+     regex_t valid_line_re, comment_re;
+#define regmatch_size 12
+     regmatch_t regmatch[regmatch_size];
+
+     if (opkg_init_options_array(conf, &options)<0)
+        return ENOMEM;
+
+     if (file == NULL) {
+         fprintf(stderr, "%s: failed to open %s: %s\n",
+                 __FUNCTION__, filename, strerror(errno));
+         free(options);
+         return errno;
+     }
+     opkg_message(conf, OPKG_NOTICE, "loading conf file %s\n", filename);
+
+     err = xregcomp(&comment_re, 
+                   "^[[:space:]]*(#.*|[[:space:]]*)$",
+                   REG_EXTENDED);
+     if (err) {
+         free(options);
+         return err;
+     }
+     err = xregcomp(&valid_line_re, "^[[:space:]]*(\"([^\"]*)\"|([^[:space:]]*))[[:space:]]*(\"([^\"]*)\"|([^[:space:]]*))[[:space:]]*(\"([^\"]*)\"|([^[:space:]]*))([[:space:]]+([^[:space:]]+))?[[:space:]]*$", REG_EXTENDED);
+     if (err) {
+         free(options);
+         return err;
+     }
+
+     while(1) {
+         int line_num = 0;
+         char *line;
+         char *type, *name, *value, *extra;
+
+         line = file_read_line_alloc(file);
+         line_num++;
+         if (line == NULL) {
+              break;
+         }
+
+         str_chomp(line);
+
+         if (regexec(&comment_re, line, 0, 0, 0) == 0) {
+              goto NEXT_LINE;
+         }
+
+         if (regexec(&valid_line_re, line, regmatch_size, regmatch, 0) == REG_NOMATCH) {
+              str_chomp(line);
+              fprintf(stderr, "%s:%d: Ignoring invalid line: `%s'\n",
+                      filename, line_num, line);
+              goto NEXT_LINE;
+         }
+
+         /* This has to be so ugly to deal with optional quotation marks */
+         if (regmatch[2].rm_so > 0) {
+              type = strndup(line + regmatch[2].rm_so,
+                             regmatch[2].rm_eo - regmatch[2].rm_so);
+         } else {
+              type = strndup(line + regmatch[3].rm_so,
+                             regmatch[3].rm_eo - regmatch[3].rm_so);
+         }
+         if (regmatch[5].rm_so > 0) {
+              name = strndup(line + regmatch[5].rm_so,
+                             regmatch[5].rm_eo - regmatch[5].rm_so);
+         } else {
+              name = strndup(line + regmatch[6].rm_so,
+                             regmatch[6].rm_eo - regmatch[6].rm_so);
+         }
+         if (regmatch[8].rm_so > 0) {
+              value = strndup(line + regmatch[8].rm_so,
+                              regmatch[8].rm_eo - regmatch[8].rm_so);
+         } else {
+              value = strndup(line + regmatch[9].rm_so,
+                              regmatch[9].rm_eo - regmatch[9].rm_so);
+         }
+         extra = NULL;
+         if (regmatch[11].rm_so > 0) {
+              extra = strndup (line + regmatch[11].rm_so,
+                               regmatch[11].rm_eo - regmatch[11].rm_so);
+         }
+
+         /* We use the tmp_dest_nv_pair_list below instead of
+            conf->pkg_dest_list because we might encounter an
+            offline_root option later and that would invalidate the
+            directories we would have computed in
+            pkg_dest_list_init. (We do a similar thing with
+            tmp_src_nv_pair_list for sake of symmetry.) */
+         if (strcmp(type, "option") == 0) {
+              opkg_conf_set_option(options, name, value);
+         } else if (strcmp(type, "src") == 0) {
+              if (!nv_pair_list_find(pkg_src_list, name)) {
+                   pkg_src_list_append (pkg_src_list, name, value, extra, 0);
+              } else {
+                   opkg_message(conf, OPKG_ERROR, "ERROR: duplicate src declaration.  Skipping:\n\t src %s %s\n",
+                                name, value);
+              }
+         } else if (strcmp(type, "src/gz") == 0) {
+              if (!nv_pair_list_find(pkg_src_list, name)) {
+                   pkg_src_list_append (pkg_src_list, name, value, extra, 1);
+              } else {
+                   opkg_message(conf, OPKG_ERROR, "ERROR: duplicate src declaration.  Skipping:\n\t src %s %s\n",
+                                name, value);
+              }
+         } else if (strcmp(type, "dest") == 0) {
+              nv_pair_list_append(tmp_dest_nv_pair_list, name, value);
+         } else if (strcmp(type, "lists_dir") == 0) {
+              *lists_dir = realloc(*lists_dir,strlen(value)+1);
+               if (*lists_dir == NULL) {
+                   opkg_message(conf, OPKG_ERROR, "ERROR: Not enough memory\n");
+                   free(options);
+                   return EINVAL;
+               }
+               sprintf (*lists_dir,"%s",value);
+         } else if (strcmp(type, "arch") == 0) {
+              opkg_message(conf, OPKG_INFO, "supported arch %s priority (%s)\n", name, value);
+              if (!value) {
+                   opkg_message(conf, OPKG_NOTICE, "defaulting architecture %s priority to 10\n", name);
+                   value = strdup("10");
+              }
+              nv_pair_list_append(&conf->arch_list, strdup(name), strdup(value));
+         } else {
+              fprintf(stderr, "WARNING: Ignoring unknown configuration "
+                      "parameter: %s %s %s\n", type, name, value);
+              free(options);
+              return EINVAL;
+         }
+
+         free(type);
+         free(name);
+         free(value);
+         if (extra)
+              free (extra);
+
+     NEXT_LINE:
+         free(line);
+     }
+
+     free(options);
+     regfree(&comment_re);
+     regfree(&valid_line_re);
+     fclose(file);
+
+     return 0;
+}
+
+static int opkg_conf_set_option(const opkg_option_t *options,
+                               const char *name, const char *value)
+{
+     int i = 0;
+     while (options[i].name) {
+         if (strcmp(options[i].name, name) == 0) {
+              switch (options[i].type) {
+              case OPKG_OPT_TYPE_BOOL:
+                   *((int *)options[i].value) = 1;
+                   return 0;
+              case OPKG_OPT_TYPE_INT:
+                   if (value) {
+                        *((int *)options[i].value) = atoi(value);
+                        return 0;
+                   } else {
+                        printf("%s: Option %s need an argument\n",
+                               __FUNCTION__, name);
+                        return EINVAL;
+                   }               
+              case OPKG_OPT_TYPE_STRING:
+                   if (value) {
+                        *((char **)options[i].value) = strdup(value);
+                        return 0;
+                   } else {
+                        printf("%s: Option %s need an argument\n",
+                               __FUNCTION__, name);
+                        return EINVAL;
+                   }
+              }
+         }
+         i++;
+     }
+    
+     fprintf(stderr, "%s: Unrecognized option: %s=%s\n",
+            __FUNCTION__, name, value);
+     return EINVAL;
+}
+
+int opkg_conf_write_status_files(opkg_conf_t *conf)
+{
+     pkg_dest_list_elt_t *iter;
+     pkg_dest_t *dest;
+     pkg_vec_t *all;
+     pkg_t *pkg;
+     register int i;
+     int err;
+
+     if (conf->noaction)
+         return 0;
+     for (iter = conf->pkg_dest_list.head; iter; iter = iter->next) {
+         dest = iter->data;
+         dest->status_file = fopen(dest->status_file_tmp_name, "w");
+         if (dest->status_file == NULL) {
+              fprintf(stderr, "%s: Can't open status file: %s for writing: %s\n",
+                      __FUNCTION__, dest->status_file_name, strerror(errno));
+         }
+     }
+
+     all = pkg_vec_alloc();
+     pkg_hash_fetch_available(&conf->pkg_hash, all);
+
+     for(i = 0; i < all->len; i++) {
+         pkg = all->pkgs[i];
+         /* We don't need most uninstalled packages in the status file */
+         if (pkg->state_status == SS_NOT_INSTALLED
+             && (pkg->state_want == SW_UNKNOWN
+                 || pkg->state_want == SW_DEINSTALL
+                 || pkg->state_want == SW_PURGE)) {
+              continue;
+         }
+         if (!pkg) {
+           fprintf(stderr, "Null package\n");
+         }
+         if (pkg->dest == NULL) {
+              fprintf(stderr, "%s: ERROR: Can't write status for "
+                      "package %s since it has a NULL dest\n",
+                      __FUNCTION__, pkg->name);
+              continue;
+         }
+         if (pkg->dest->status_file) {
+              pkg_print_status(pkg, pkg->dest->status_file);
+         }
+     }
+
+     pkg_vec_free(all);
+
+     for (iter = conf->pkg_dest_list.head; iter; iter = iter->next) {
+         dest = iter->data;
+         if (dest->status_file) {
+              err = ferror(dest->status_file);
+              fclose(dest->status_file);
+              dest->status_file = NULL;
+              if (!err) {
+                   file_move(dest->status_file_tmp_name, dest->status_file_name);
+              } else {
+                   fprintf(stderr, "%s: ERROR: An error has occurred writing %s, "
+                           "retaining old %s\n", __FUNCTION__, 
+                           dest->status_file_tmp_name, dest->status_file_name);
+              }
+         }
+     }
+
+     return 0;
+}
+
+
+char *root_filename_alloc(opkg_conf_t *conf, char *filename)
+{
+     char *root_filename;
+     sprintf_alloc(&root_filename, "%s%s", (conf->offline_root ? conf->offline_root : ""), filename);
+     return root_filename;
+}
diff --git a/libopkg/opkg_conf.h b/libopkg/opkg_conf.h
new file mode 100644 (file)
index 0000000..4b50900
--- /dev/null
@@ -0,0 +1,107 @@
+/* opkg_conf.h - the itsy package management system
+
+   Carl D. Worth
+
+   Copyright (C) 2001 University of Southern California
+
+   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, 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
+   General Public License for more details.
+*/
+
+#ifndef OPKG_CONF_H
+#define OPKG_CONF_H
+
+typedef struct opkg_conf opkg_conf_t;
+
+#include "hash_table.h"
+#include "opkg.h"
+#include "args.h"
+#include "pkg.h"
+#include "pkg_hash.h"
+#include "pkg_src_list.h"
+#include "pkg_dest_list.h"
+#include "nv_pair_list.h"
+
+#define OPKG_CONF_DEFAULT_TMP_DIR_BASE "/tmp"
+#define OPKG_CONF_TMP_DIR_SUFFIX "opkg-XXXXXX"
+#define OPKG_CONF_LISTS_DIR  OPKG_STATE_DIR_PREFIX "/lists"
+#define OPKG_CONF_PENDING_DIR OPKG_STATE_DIR_PREFIX "/pending"
+
+/* In case the config file defines no dest */
+#define OPKG_CONF_DEFAULT_DEST_NAME "root"
+#define OPKG_CONF_DEFAULT_DEST_ROOT_DIR "/"
+
+#define OPKG_CONF_DEFAULT_HASH_LEN 1024
+
+struct opkg_conf
+{
+     pkg_src_list_t pkg_src_list;
+     pkg_dest_list_t pkg_dest_list;
+     nv_pair_list_t arch_list;
+
+     int restrict_to_default_dest;
+     pkg_dest_t *default_dest;
+
+     char *tmp_dir;
+     const char *lists_dir;
+     const char *pending_dir;
+
+     /* options */
+     int force_depends;
+     int force_defaults;
+     int force_overwrite;
+     int force_downgrade;
+     int force_reinstall;
+     int force_space;
+     int force_removal_of_dependent_packages;
+     int force_removal_of_essential_packages;
+     int nodeps; /* do not follow dependences */
+     int verbose_wget;
+     int multiple_providers;
+     char *offline_root;
+     char *offline_root_pre_script_cmd;
+     char *offline_root_post_script_cmd;
+     int query_all;
+     int verbosity;
+     int noaction;
+
+     /* proxy options */
+     char *http_proxy;
+     char *ftp_proxy;
+     char *no_proxy;
+     char *proxy_user;
+     char *proxy_passwd;
+
+     hash_table_t pkg_hash;
+     hash_table_t file_hash;
+     hash_table_t obs_file_hash;
+};
+
+enum opkg_option_type {
+     OPKG_OPT_TYPE_BOOL,
+     OPKG_OPT_TYPE_INT,
+     OPKG_OPT_TYPE_STRING
+};
+typedef enum opkg_option_type opkg_option_type_t;
+
+typedef struct opkg_option opkg_option_t;
+struct opkg_option {
+     const char *name;
+     const opkg_option_type_t type;
+     const void *value;
+};
+
+int opkg_conf_init(opkg_conf_t *conf, const args_t *args);
+void opkg_conf_deinit(opkg_conf_t *conf);
+
+int opkg_conf_write_status_files(opkg_conf_t *conf);
+char *root_filename_alloc(opkg_conf_t *conf, char *filename);
+
+#endif
diff --git a/libopkg/opkg_configure.c b/libopkg/opkg_configure.c
new file mode 100644 (file)
index 0000000..8309e40
--- /dev/null
@@ -0,0 +1,48 @@
+/* opkg_configure.c - the itsy package management system
+
+   Carl D. Worth
+
+   Copyright (C) 2001 University of Southern California
+
+   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, 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
+   General Public License for more details.
+*/
+
+#include "opkg.h"
+
+#include "opkg_configure.h"
+#include "opkg_state.h"
+
+int opkg_configure(opkg_conf_t *conf, pkg_t *pkg)
+{
+    int err;
+
+    /* DPKG_INCOMPATIBILITY:
+       dpkg actually does some conffile handling here, rather than at the
+       end of opkg_install(). Do we care? */
+    /* DPKG_INCOMPATIBILITY:
+       dpkg actually includes a version number to this script call */
+
+    char *pkgid;
+    sprintf_alloc (&pkgid, "%s;%s;%s;", pkg->name, pkg->version, pkg->architecture);
+    opkg_set_current_state (OPKG_STATE_CONFIGURING_PKG, pkgid);
+    free (pkgid);
+
+    err = pkg_run_script(conf, pkg, "postinst", "configure");
+    if (err) {
+       printf("ERROR: %s.postinst returned %d\n", pkg->name, err);
+       return err;
+    }
+
+    opkg_state_changed++;
+    opkg_set_current_state (OPKG_STATE_NONE, NULL);
+    return 0;
+}
+
diff --git a/libopkg/opkg_configure.h b/libopkg/opkg_configure.h
new file mode 100644 (file)
index 0000000..f56f0e4
--- /dev/null
@@ -0,0 +1,25 @@
+/* opkg_configure.h - the itsy package management system
+
+   Carl D. Worth
+
+   Copyright (C) 2001 University of Southern California
+
+   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, 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
+   General Public License for more details.
+*/
+
+#ifndef OPKG_CONFIGURE_H
+#define OPKG_CONFIGURE_H
+
+#include "opkg_conf.h"
+
+int opkg_configure(opkg_conf_t *opkg_conf, pkg_t *pkg);
+
+#endif
diff --git a/libopkg/opkg_download.c b/libopkg/opkg_download.c
new file mode 100644 (file)
index 0000000..bbd6efe
--- /dev/null
@@ -0,0 +1,346 @@
+/* vi: set noexpandtab sw=4 sts=4: */
+/* opkg_download.c - the itsy package management system
+
+   Carl D. Worth
+
+   Copyright (C) 2001 University of Southern California
+   Copyright (C) 2008 OpenMoko Inc
+
+   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, 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
+   General Public License for more details.
+*/
+#include "config.h"
+#include <curl/curl.h>
+#ifdef HAVE_GPGME
+#include <gpgme.h>
+#endif
+
+#include "opkg.h"
+#include "opkg_download.h"
+#include "opkg_message.h"
+#include "opkg_state.h"
+
+#include "sprintf_alloc.h"
+#include "xsystem.h"
+#include "file_util.h"
+#include "str_util.h"
+
+#ifdef OPKG_LIB
+#include "libopkg.h"
+opkg_download_progress_callback opkg_cb_download_progress = NULL;
+#endif
+
+int
+curl_progress_func (char* url,
+                   double t, /* dltotal */
+                   double d, /* dlnow */
+                   double ultotal,
+                   double ulnow)
+{
+    int i;
+    int p = (t) ? d*100/t : 0;
+
+#ifdef OPKG_LIB
+    if (opkg_cb_download_progress)
+    {
+       static int prev = -1;
+
+       /* don't report the same percentage multiple times
+        * (this can occur due to rounding) */
+       if (prev == p)
+           return 0;
+       prev = p;
+
+       opkg_cb_download_progress (p, url);
+       return 0;
+    }
+#endif
+
+    /* skip progress bar if we haven't done started yet
+     * this prevents drawing the progress bar if we receive an error such as
+     * file not found */
+    if (t == 0)
+       return 0;
+
+    printf ("\r%3d%% |", p);
+    for (i = 1; i < 73; i++)
+    {
+       if (i <= p * 0.73)
+           printf ("=");
+       else
+           printf ("-");
+    }
+    printf ("|");
+    fflush(stdout);
+    return 0;
+}
+
+int opkg_download(opkg_conf_t *conf, const char *src, const char *dest_file_name)
+{
+    int err = 0;
+
+    char *src_basec = strdup(src);
+    char *src_base = basename(src_basec);
+    char *tmp_file_location;
+
+    opkg_message(conf,OPKG_NOTICE,"Downloading %s\n", src);
+       
+    fflush(stdout);
+    
+    if (str_starts_with(src, "file:")) {
+       int ret;
+       const char *file_src = src + 5;
+       opkg_message(conf,OPKG_INFO,"Copying %s to %s...", file_src, dest_file_name);
+       ret = file_copy(src + 5, dest_file_name);
+       opkg_message(conf,OPKG_INFO,"Done\n");
+       return ret;
+    }
+
+    sprintf_alloc(&tmp_file_location, "%s/%s", conf->tmp_dir, src_base);
+    err = unlink(tmp_file_location);
+    if (err && errno != ENOENT) {
+       opkg_message(conf,OPKG_ERROR, "%s: ERROR: failed to unlink %s: %s\n",
+               __FUNCTION__, tmp_file_location, strerror(errno));
+       free(tmp_file_location);
+       return errno;
+    }
+
+    if (conf->http_proxy) {
+       opkg_message(conf,OPKG_DEBUG,"Setting environment variable: http_proxy = %s\n", conf->http_proxy);
+       setenv("http_proxy", conf->http_proxy, 1);
+    }
+    if (conf->ftp_proxy) {
+       opkg_message(conf,OPKG_DEBUG,"Setting environment variable: ftp_proxy = %s\n", conf->ftp_proxy);
+       setenv("ftp_proxy", conf->ftp_proxy, 1);
+    }
+    if (conf->no_proxy) {
+       opkg_message(conf,OPKG_DEBUG,"Setting environment variable: no_proxy = %s\n", conf->no_proxy);
+       setenv("no_proxy", conf->no_proxy, 1);
+    }
+
+    /* XXX: BUG rewrite to use execvp or else busybox's internal wget -Jamey 7/23/2002 */ 
+#if 0
+    sprintf_alloc(&cmd, "wget --passive-ftp %s %s%s %s%s %s -P %s %s",
+                 (conf->http_proxy || conf->ftp_proxy) ? "--proxy=on" : "",
+                 conf->proxy_user ? "--proxy-user=" : "",
+                 conf->proxy_user ? conf->proxy_user : "",
+                 conf->proxy_passwd ? "--proxy-passwd=" : "",
+                 conf->proxy_passwd ? conf->proxy_passwd : "",
+                 conf->verbose_wget ? "" : "-q",
+                 conf->tmp_dir,
+                 src);
+    err = xsystem(cmd);
+    if (err) {
+       if (err != -1) {
+           opkg_message(conf,OPKG_ERROR, "%s: ERROR: Command failed with return value %d: `%s'\n",
+                   __FUNCTION__, err, cmd);
+       } 
+       unlink(tmp_file_location);
+       free(tmp_file_location);
+       free(src_basec);
+       free(cmd);
+       return EINVAL;
+    }
+    free(cmd);
+#endif
+    CURL *curl;
+    CURLcode res;
+    FILE * file = fopen (tmp_file_location, "w");
+
+    curl = curl_easy_init ();
+    if (curl)
+    {
+       curl_easy_setopt (curl, CURLOPT_URL, src);
+       curl_easy_setopt (curl, CURLOPT_WRITEDATA, file);
+       curl_easy_setopt (curl, CURLOPT_NOPROGRESS, 0);
+       curl_easy_setopt (curl, CURLOPT_PROGRESSDATA, src);
+       curl_easy_setopt (curl, CURLOPT_PROGRESSFUNCTION, curl_progress_func);
+       curl_easy_setopt (curl, CURLOPT_FAILONERROR, 1);
+       if (conf->http_proxy || conf->ftp_proxy)
+       {
+           char *userpwd;
+           sprintf_alloc (&userpwd, "%s:%s", conf->proxy_user,
+                   conf->proxy_passwd);
+           curl_easy_setopt(curl, CURLOPT_PROXYUSERPWD, userpwd);
+           free (userpwd);
+       }
+       res = curl_easy_perform (curl);
+       curl_easy_cleanup (curl);
+       fclose (file);
+       if (res)
+       {
+           long error_code;
+           curl_easy_getinfo(curl, CURLINFO_RESPONSE_CODE, &error_code);
+           opkg_message(conf, OPKG_ERROR, "Failed to download %s, error %d\n", src, error_code);
+           return res;
+       }
+
+    }
+    else
+       return -1;
+
+    printf ("\n");
+
+    err = file_move(tmp_file_location, dest_file_name);
+
+    free(tmp_file_location);
+    free(src_basec);
+
+    if (err) {
+       return err;
+    }
+
+    return 0;
+}
+
+int opkg_download_pkg(opkg_conf_t *conf, pkg_t *pkg, const char *dir)
+{
+    int err;
+    char *url;
+    char *pkgid;
+
+    if (pkg->src == NULL) {
+       opkg_message(conf,OPKG_ERROR, "ERROR: Package %s (parent %s) is not available from any configured src.\n",
+               pkg->name, pkg->parent->name);
+       return -1;
+    }
+
+    sprintf_alloc (&pkgid, "%s;%s;%s;", pkg->name, pkg->version, pkg->architecture);
+    opkg_set_current_state (OPKG_STATE_DOWNLOADING_PKG, pkgid);
+    free (pkgid);
+
+    sprintf_alloc(&url, "%s/%s", pkg->src->value, pkg->filename);
+
+    /* XXX: BUG: The pkg->filename might be something like
+       "../../foo.ipk". While this is correct, and exactly what we
+       want to use to construct url above, here we actually need to
+       use just the filename part, without any directory. */
+    sprintf_alloc(&pkg->local_filename, "%s/%s", dir, pkg->filename);
+
+    err = opkg_download(conf, url, pkg->local_filename);
+    free(url);
+
+    opkg_set_current_state (OPKG_STATE_NONE, NULL);
+    return err;
+}
+
+/*
+ * Downloads file from url, installs in package database, return package name. 
+ */
+int opkg_prepare_url_for_install(opkg_conf_t *conf, const char *url, char **namep)
+{
+     int err = 0;
+     pkg_t *pkg;
+     pkg = pkg_new();
+     if (pkg == NULL)
+         return ENOMEM;
+
+     if (str_starts_with(url, "http://")
+        || str_starts_with(url, "ftp://")) {
+         char *tmp_file;
+         char *file_basec = strdup(url);
+         char *file_base = basename(file_basec);
+
+         sprintf_alloc(&tmp_file, "%s/%s", conf->tmp_dir, file_base);
+         err = opkg_download(conf, url, tmp_file);
+         if (err)
+              return err;
+
+         err = pkg_init_from_file(pkg, tmp_file);
+         if (err)
+              return err;
+         pkg->local_filename = strdup(tmp_file);
+
+         free(tmp_file);
+         free(file_basec);
+
+     } else if (strcmp(&url[strlen(url) - 4], OPKG_PKG_EXTENSION) == 0
+               || strcmp(&url[strlen(url) - 4], DPKG_PKG_EXTENSION) == 0) {
+
+         err = pkg_init_from_file(pkg, url);
+         if (err)
+              return err;
+         pkg->local_filename = strdup(url);
+         opkg_message(conf, OPKG_DEBUG2, "Package %s provided by hand (%s).\n", pkg->name,pkg->local_filename);
+          pkg->provided_by_hand = 1;
+
+     } else {
+       pkg_deinit(pkg);
+       free(pkg);
+       return 0;
+     }
+
+     if (!pkg->architecture) {
+         opkg_message(conf, OPKG_ERROR, "Package %s has no Architecture defined.\n", pkg->name);
+         return -EINVAL;
+     }
+
+     pkg->dest = conf->default_dest;
+     pkg->state_want = SW_INSTALL;
+     pkg->state_flag |= SF_PREFER;
+     pkg = hash_insert_pkg(&conf->pkg_hash, pkg, 1,conf);  
+     if ( pkg == NULL ){
+        fprintf(stderr, "%s : This should never happen. Report this Bug in bugzilla please \n ",__FUNCTION__);
+        return 0;
+     }
+     if (namep) {
+         *namep = strdup(pkg->name);
+     }
+     return 0;
+}
+
+int
+opkg_verify_file (char *text_file, char *sig_file)
+{
+#ifdef HAVE_GPGME
+    int status = -1;
+    gpgme_ctx_t ctx;
+    gpgme_data_t sig, text;
+    gpgme_error_t err = -1;
+    gpgme_verify_result_t result;
+    gpgme_signature_t s;
+    
+    err = gpgme_new (&ctx);
+
+    if (err)
+       return -1;
+
+    err = gpgme_data_new_from_file (&sig, sig_file, 1); 
+    if (err)
+       return -1;
+
+    err = gpgme_data_new_from_file (&text, text_file, 1); 
+    if (err)
+       return -1;
+
+    err = gpgme_op_verify (ctx, sig, text, NULL);
+
+    result = gpgme_op_verify_result (ctx);
+
+    /* see if any of the signitures matched */
+    s = result->signatures;
+    while (s)
+    {
+       status = gpg_err_code (s->status);
+       if (status == GPG_ERR_NO_ERROR)
+           break;
+       s = s->next;
+    }
+
+    gpgme_data_release (sig);
+    gpgme_data_release (text);
+    gpgme_release (ctx);
+
+    return status;
+#else
+    printf ("Signature check skipped because GPG support was not enabled in this build\n");
+    return 0;
+#endif
+}
diff --git a/libopkg/opkg_download.h b/libopkg/opkg_download.h
new file mode 100644 (file)
index 0000000..d3f419d
--- /dev/null
@@ -0,0 +1,31 @@
+/* opkg_download.h - the itsy package management system
+
+   Carl D. Worth
+
+   Copyright (C) 2001 University of Southern California
+
+   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, 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
+   General Public License for more details.
+*/
+
+#ifndef OPKG_DOWNLOAD_H
+#define OPKG_DOWNLOAD_H
+
+#include "opkg_conf.h"
+
+int opkg_download(opkg_conf_t *conf, const char *src, const char *dest_file_name);
+int opkg_download_pkg(opkg_conf_t *conf, pkg_t *pkg, const char *dir);
+/*
+ * Downloads file from url, installs in package database, return package name. 
+ */
+int opkg_prepare_url_for_install(opkg_conf_t *conf, const char *url, char **namep);
+
+int opkg_verify_file (char *text_file, char *sig_file);
+#endif
diff --git a/libopkg/opkg_extract_test.c b/libopkg/opkg_extract_test.c
new file mode 100644 (file)
index 0000000..83e23e3
--- /dev/null
@@ -0,0 +1,46 @@
+#include <stdio.h>
+#include <stdlib.h>
+#include "libbb/libbb.h"
+
+/*
+ * build thus: 
+
+ * gcc -o opkg_extract_test opkg_extract_test.c -I./busybox-0.60.2/libbb -L./busybox-0.60.2 -lbb
+ *
+ */
+const char * applet_name;
+
+int main(int argc, char * argv[])
+{
+  /*
+   * see libbb.h and let your imagination run wild
+   * or, set the last item below to extract_one_to_buffer, and you get the control file in 
+   * "returned"
+   * or, set the last one to extract_all_to_fs, and, well, guess what happens
+   */
+
+    /* enum extract_functions_e dowhat = extract_control_tar_gz | extract_unconditional | extract_one_to_buffer; */
+    enum extract_functions_e dowhat = extract_control_tar_gz | extract_all_to_fs | extract_preserve_date;
+  char * returned;
+  char * filename;
+  
+  if(argc < 2){
+    fprintf(stderr, "syntax: %s <opkg file> [<file_to_extract>]\n", argv[0]);
+    exit(0);
+  }
+  
+  if (argc < 3){
+    filename=NULL;
+  } else {
+    filename = argv[2];
+  }
+
+  returned = deb_extract(argv[1], stdout, dowhat, NULL, filename);
+  
+  if(returned)
+    fprintf(stderr, "returned %s\n", returned);
+  else
+    fprintf(stderr, "extract returned nuthin'\n");
+
+  return 0;
+}
diff --git a/libopkg/opkg_hash_test.c b/libopkg/opkg_hash_test.c
new file mode 100644 (file)
index 0000000..934dac7
--- /dev/null
@@ -0,0 +1,79 @@
+/* opkg_hash_test.c - the itsy package management system
+
+   Carl D. Worth
+
+   Copyright (C) 2001 University of Southern California
+
+   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, 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
+   General Public License for more details.
+*/
+
+#include "opkg.h"
+
+#include "hash_table.h"
+#include "opkg_utils.h"
+#include "pkg_hash.h"
+
+int main(int argc, char *argv[])
+{
+     opkg_conf_t conf;
+     hash_table_t *hash = &conf.pkg_hash;
+     pkg_vec_t * pkg_vec;
+
+    if (argc < 3) {
+       fprintf(stderr, "Usage: %s <pkgs_file1> <pkgs_file2> [pkg_name...]\n", argv[0]);
+       exit(1);
+    }
+    pkg_hash_init("test", hash, 1024);
+
+    pkg_hash_add_from_file(&conf, argv[1], NULL, NULL, 0);
+    pkg_hash_add_from_file(&conf, argv[2], NULL, NULL, 0);
+
+    if (argc < 4) {
+       pkg_print_info( pkg_hash_fetch_by_name_version(hash, "libc6", "2.2.3-2"), stdout);
+       /*      for(i = 0; i < pkg_vec->len; i++)
+               pkg_print(pkg_vec->pkgs[i], stdout);
+       */
+    } else {
+       int i, j, k;
+       char **unresolved;
+
+       pkg_vec_t * dep_vec;
+       for (i = 3; i < argc; i++) {
+           pkg_vec = pkg_vec_fetch_by_name(hash, argv[i]);
+           if (pkg_vec == NULL) {
+               fprintf(stderr, "*** WARNING: Unknown package: %s\n\n", argv[i]);
+               continue;
+           }
+
+           for(j = 0; j < pkg_vec->len; j++){
+               pkg_print_info(pkg_vec->pkgs[j], stdout);
+               dep_vec = pkg_vec_alloc();
+               pkg_hash_fetch_unsatisfied_dependencies(&conf,
+                                                       pkg_vec->pkgs[j],
+                                                       dep_vec,
+                                                       &unresolved);
+               if(dep_vec){
+                   fprintf(stderr, "and the unsatisfied dependencies are:\n");
+                   for(k = 0; k < dep_vec->len; k++){
+                       fprintf(stderr, "%s version %s\n", dep_vec->pkgs[k]->name, dep_vec->pkgs[k]->version);
+                   }
+               }
+               
+               fputs("", stdout);
+               
+           }
+       }
+    }
+
+    pkg_hash_deinit(hash);
+
+    return 0;
+}
diff --git a/libopkg/opkg_install.c b/libopkg/opkg_install.c
new file mode 100644 (file)
index 0000000..599ae4d
--- /dev/null
@@ -0,0 +1,1952 @@
+/* opkg_install.c - the itsy package management system
+
+   Carl D. Worth
+
+   Copyright (C) 2001 University of Southern California
+
+   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, 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
+   General Public License for more details.
+*/
+
+#include "opkg.h"
+#include <errno.h>
+#include <dirent.h>
+#include <glob.h>
+#include <time.h>
+#include <signal.h>
+typedef void (*sighandler_t)(int);
+
+#include "pkg.h"
+#include "pkg_hash.h"
+#include "pkg_extract.h"
+
+#include "opkg_install.h"
+#include "opkg_configure.h"
+#include "opkg_download.h"
+#include "opkg_remove.h"
+
+#include "opkg_utils.h"
+#include "opkg_message.h"
+#include "opkg_state.h"
+
+#include "sprintf_alloc.h"
+#include "file_util.h"
+#include "str_util.h"
+#include "xsystem.h"
+#include "user.h"
+
+int satisfy_dependencies_for(opkg_conf_t *conf, pkg_t *pkg);
+static int verify_pkg_installable(opkg_conf_t *conf, pkg_t *pkg);
+static int unpack_pkg_control_files(opkg_conf_t *conf, pkg_t *pkg);
+
+static int prerm_upgrade_old_pkg(opkg_conf_t *conf, pkg_t *pkg, pkg_t *old_pkg);
+static int prerm_upgrade_old_pkg_unwind(opkg_conf_t *conf, pkg_t *pkg, pkg_t *old_pkg);
+static int prerm_deconfigure_conflictors(opkg_conf_t *conf, pkg_t *pkg, pkg_vec_t *conflictors);
+static int prerm_deconfigure_conflictors_unwind(opkg_conf_t *conf, pkg_t *pkg, pkg_vec_t *conflictors);
+static int preinst_configure(opkg_conf_t *conf, pkg_t *pkg, pkg_t *old_pkg);
+static int preinst_configure_unwind(opkg_conf_t *conf, pkg_t *pkg, pkg_t *old_pkg);
+static int check_data_file_clashes(opkg_conf_t *conf, pkg_t *pkg, pkg_t *old_pkg);
+static int check_data_file_clashes_change(opkg_conf_t *conf, pkg_t *pkg, pkg_t *old_pkg);
+static int check_data_file_clashes_unwind(opkg_conf_t *conf, pkg_t *pkg, pkg_t *old_pkg);
+static int backup_modified_conffiles(opkg_conf_t *conf, pkg_t *pkg, pkg_t *old_pkg);
+static int backup_modified_conffiles_unwind(opkg_conf_t *conf, pkg_t *pkg, pkg_t *old_pkg);
+static int postrm_upgrade_old_pkg(opkg_conf_t *conf, pkg_t *pkg, pkg_t *old_pkg);
+static int postrm_upgrade_old_pkg_unwind(opkg_conf_t *conf, pkg_t *pkg, pkg_t *old_pkg);
+
+static int remove_obsolesced_files(opkg_conf_t *conf, pkg_t *pkg, pkg_t *old_pkg);
+static int install_maintainer_scripts(opkg_conf_t *conf, pkg_t *pkg, pkg_t *old_pkg);
+static int remove_disappeared(opkg_conf_t *conf, pkg_t *pkg);
+static int install_data_files(opkg_conf_t *conf, pkg_t *pkg);
+static int resolve_conffiles(opkg_conf_t *conf, pkg_t *pkg);
+
+static int cleanup_temporary_files(opkg_conf_t *conf, pkg_t *pkg);
+
+static int user_prefers_old_conffile(const char *file, const char *backup);
+
+static char *backup_filename_alloc(const char *file_name);
+static int backup_make_backup(opkg_conf_t *conf, const char *file_name);
+static int backup_exists_for(const char *file_name);
+static int backup_remove(const char *file_name);
+
+
+int opkg_install_from_file(opkg_conf_t *conf, const char *filename)
+{
+     int err, cmp;
+     pkg_t *pkg, *old;
+     char *old_version, *new_version;
+
+     pkg = pkg_new();
+     if (pkg == NULL) {
+         return ENOMEM;
+     }
+
+     err = pkg_init_from_file(pkg, filename);
+     if (err) {
+         return err;
+     }
+
+     if (!pkg->architecture) {
+         opkg_message(conf, OPKG_ERROR, "Package %s has no Architecture defined.\n", pkg->name);
+         return -EINVAL;
+     }
+
+     /* XXX: CLEANUP: hash_insert_pkg has a nasty side effect of possibly
+       freeing the pkg that we pass in. It might be nice to clean this up
+       if possible.  */
+     pkg = hash_insert_pkg(&conf->pkg_hash, pkg, 1,conf);
+     old = pkg_hash_fetch_installed_by_name(&conf->pkg_hash, pkg->name);
+
+     pkg->local_filename = strdup(filename);
+
+     if (old) {
+         old_version = pkg_version_str_alloc(old);
+         new_version = pkg_version_str_alloc(pkg);
+
+         cmp = pkg_compare_versions(old, pkg);
+          if ( (conf->force_downgrade==1) && (cmp > 0) ){     /* We've been asked to allow downgrade  and version is precedent */
+             cmp = -1 ;                                       /* then we force opkg to downgrade */ 
+                                                              /* We need to use a value < 0 because in the 0 case we are asking to */
+                                                              /* reinstall, and some check could fail asking the "force-reinstall" option */
+          } 
+         if (cmp > 0) {
+                opkg_message(conf, OPKG_NOTICE,
+                             "Not downgrading package %s on %s from %s to %s.\n",
+                             old->name, old->dest->name, old_version, new_version);
+                pkg->state_want = SW_DEINSTALL;
+                pkg->state_flag |= SF_OBSOLETE;
+                free(old_version);
+                free(new_version);
+                return 0;
+         } else {
+              free(old_version);
+              free(new_version);
+         }
+     }
+
+     opkg_message(conf, OPKG_DEBUG2,"Function: %s calling opkg_install_pkg \n",__FUNCTION__);
+     return opkg_install_pkg(conf, pkg,0);
+}
+
+opkg_error_t opkg_install_by_name(opkg_conf_t *conf, const char *pkg_name)
+{
+     int cmp;
+     pkg_t *old, *new;
+     char *old_version, *new_version;
+
+     opkg_message(conf, OPKG_DEBUG2, " Getting old  from pkg_hash_fetch \n" );
+     old = pkg_hash_fetch_installed_by_name(&conf->pkg_hash, pkg_name);
+     if ( old ) 
+        opkg_message(conf, OPKG_DEBUG2, " Old versions from pkg_hash_fetch %s \n",  old->version );
+    
+     opkg_message(conf, OPKG_DEBUG2, " Getting new  from pkg_hash_fetch \n" );
+     new = pkg_hash_fetch_best_installation_candidate_by_name(conf, pkg_name);
+     if ( new ) 
+        opkg_message(conf, OPKG_DEBUG2, " New versions from pkg_hash_fetch %s \n",  new->version );
+
+/* Pigi Basically here is broken the version stuff.
+   What's happening is that nothing provide the version to differents 
+   functions, so the returned struct is always the latest.
+   That's why the install by name don't work.
+*/
+     opkg_message(conf, OPKG_DEBUG2, " Versions from pkg_hash_fetch in %s ", __FUNCTION__ );
+
+     if ( old ) 
+        opkg_message(conf, OPKG_DEBUG2, " old %s ", old->version );
+     if ( new ) 
+        opkg_message(conf, OPKG_DEBUG2, " new %s ", new->version );
+     opkg_message(conf, OPKG_DEBUG2, " \n");
+
+     if (new == NULL) {
+         return OPKG_PKG_HAS_NO_CANDIDATE;
+     }
+
+     new->state_flag |= SF_USER;
+     if (old) {
+         old_version = pkg_version_str_alloc(old);
+         new_version = pkg_version_str_alloc(new);
+
+         cmp = pkg_compare_versions(old, new);
+          if ( (conf->force_downgrade==1) && (cmp > 0) ){     /* We've been asked to allow downgrade  and version is precedent */
+            opkg_message(conf, OPKG_DEBUG, " Forcing downgrade \n");
+             cmp = -1 ;                                       /* then we force opkg to downgrade */ 
+                                                              /* We need to use a value < 0 because in the 0 case we are asking to */
+                                                              /* reinstall, and some check could fail asking the "force-reinstall" option */
+          } 
+         opkg_message(conf, OPKG_DEBUG, 
+                      "Comparing visible versions of pkg %s:"
+                      "\n\t%s is installed "
+                      "\n\t%s is available "
+                      "\n\t%d was comparison result\n",
+                      pkg_name, old_version, new_version, cmp);
+         if (cmp == 0 && !conf->force_reinstall) {
+              opkg_message(conf, OPKG_NOTICE,
+                           "Package %s (%s) installed in %s is up to date.\n",
+                           old->name, old_version, old->dest->name);
+              free(old_version);
+              free(new_version);
+              return 0;
+         } else if (cmp > 0) {
+              opkg_message(conf, OPKG_NOTICE,
+                           "Not downgrading package %s on %s from %s to %s.\n",
+                           old->name, old->dest->name, old_version, new_version);
+              free(old_version);
+              free(new_version);
+              return 0;
+         } else if (cmp < 0) {
+              new->dest = old->dest;
+              old->state_want = SW_DEINSTALL;    /* Here probably the problem for bug 1277 */
+         }
+     }
+
+     /* XXX: CLEANUP: The error code of opkg_install_by_name is really
+       supposed to be an opkg_error_t, but opkg_install_pkg could
+       return any kind of integer, (might be errno from a syscall,
+       etc.). This is a real mess and will need to be cleaned up if
+       anyone ever wants to make a nice libopkg. */
+
+     opkg_message(conf, OPKG_DEBUG2,"Function: %s calling opkg_install_pkg \n",__FUNCTION__);
+     return opkg_install_pkg(conf, new,0);
+}
+
+opkg_error_t opkg_install_multi_by_name(opkg_conf_t *conf, const char *pkg_name)
+{
+     abstract_pkg_vec_t *providers = pkg_hash_fetch_all_installation_candidates (&conf->pkg_hash, pkg_name);
+     int i;
+     opkg_error_t err;
+     abstract_pkg_t *ppkg ;
+
+     if (providers == NULL)
+         return OPKG_PKG_HAS_NO_CANDIDATE;
+
+     for (i = 0; i < providers->len; i++) {
+         ppkg = abstract_pkg_vec_get(providers, i);
+          opkg_message(conf, OPKG_DEBUG2,"Function: %s calling opkg_install_by_name %d \n",__FUNCTION__, i);
+         err = opkg_install_by_name(conf, ppkg->name);
+         if (err)
+              return err;
+/* XXX Maybe ppkg should be freed ? */
+     }
+     return 0;
+}
+
+/*
+ * Walk dependence graph starting with pkg, collect packages to be
+ * installed into pkgs_needed, in dependence order.
+ */
+int pkg_mark_dependencies_for_installation(opkg_conf_t *conf, pkg_t *pkg, pkg_vec_t *pkgs_needed)
+{
+     int i, err;
+     pkg_vec_t *depends = pkg_vec_alloc();
+     char **unresolved = NULL;
+     int ndepends;
+
+     ndepends = pkg_hash_fetch_unsatisfied_dependencies(conf, 
+                                                       pkg, depends, 
+                                                       &unresolved);
+
+     if (unresolved) {
+         opkg_message(conf, OPKG_ERROR,
+                      "%s: Cannot satisfy the following dependencies for %s:\n\t",
+                      conf->force_depends ? "Warning" : "ERROR", pkg->name);
+         while (*unresolved) {
+              opkg_message(conf, OPKG_ERROR, " %s", *unresolved);
+              unresolved++;
+         }
+         opkg_message(conf, OPKG_ERROR, "\n");
+         if (! conf->force_depends) {
+              opkg_message(conf, OPKG_INFO,
+                           "This could mean that your package list is out of date or that the packages\n"
+                           "mentioned above do not yet exist (try 'opkg update'). To proceed in spite\n"
+                           "of this problem try again with the '-force-depends' option.\n");
+              pkg_vec_free(depends);
+              return OPKG_PKG_DEPS_UNSATISFIED;
+         }
+     }
+
+     if (ndepends <= 0) {
+         pkg_vec_free(depends);
+         return 0;
+     }
+
+     for (i = 0; i < depends->len; i++) {
+         pkg_t *dep = depends->pkgs[i];
+         /* The package was uninstalled when we started, but another
+            dep earlier in this loop may have depended on it and pulled
+            it in, so check first. */
+         if ((dep->state_status != SS_INSTALLED)
+             && (dep->state_status != SS_UNPACKED)
+             && (dep->state_want != SW_INSTALL)) {
+
+              /* Mark packages as to-be-installed */
+              dep->state_want = SW_INSTALL;
+
+              /* Dependencies should be installed the same place as pkg */
+              if (dep->dest == NULL) {
+                   dep->dest = pkg->dest;
+              }
+
+              err = pkg_mark_dependencies_for_installation(conf, dep, pkgs_needed);
+              if (err) {
+                   pkg_vec_free(depends);
+                   return err;
+              }
+         }
+     }
+     if (pkgs_needed)
+         pkg_vec_insert(pkgs_needed, pkg);
+
+     pkg_vec_free(depends);
+
+     return 0;
+}
+
+int name_mark_dependencies_for_installation(opkg_conf_t *conf, const char *pkg_name, pkg_vec_t *pkgs_needed)
+{
+     int cmp;
+     pkg_t *old, *new;
+     char *old_version, *new_version;
+
+     old = pkg_hash_fetch_installed_by_name(&conf->pkg_hash, pkg_name);
+    
+     new = pkg_hash_fetch_best_installation_candidate_by_name(conf, pkg_name);
+     if (new == NULL) {
+         return OPKG_PKG_HAS_NO_CANDIDATE;
+     }
+     if (old) {
+         old_version = pkg_version_str_alloc(old);
+         new_version = pkg_version_str_alloc(new);
+
+         cmp = pkg_compare_versions(old, new);
+          if ( (conf->force_downgrade==1) && (cmp > 0) ){     /* We've been asked to allow downgrade  and version is precedent */
+           opkg_message(conf, OPKG_DEBUG, " Forcing downgrade ");
+             cmp = -1 ;                                       /* then we force opkg to downgrade */ 
+                                                              /* We need to use a value < 0 because in the 0 case we are asking to */
+                                                              /* reinstall, and some check could fail asking the "force-reinstall" option */
+          } 
+         opkg_message(conf, OPKG_DEBUG, 
+                      "comparing visible versions of pkg %s:"
+                      "\n\t%s is installed "
+                      "\n\t%s is available "
+                      "\n\t%d was comparison result\n",
+                      pkg_name, old_version, new_version, cmp);
+         if (cmp == 0 && !conf->force_reinstall) {
+              opkg_message(conf, OPKG_NOTICE,
+                           "Package %s (%s) installed in %s is up to date.\n",
+                           old->name, old_version, old->dest->name);
+              free(old_version);
+              free(new_version);
+              return 0;
+         } else if (cmp > 0) {
+              opkg_message(conf, OPKG_NOTICE,
+                           "Not downgrading package %s on %s from %s to %s.\n",
+                           old->name, old->dest->name, old_version, new_version);
+              free(old_version);
+              free(new_version);
+              return 0;
+         } else if (cmp < 0) {
+              new->dest = old->dest;
+              old->state_want = SW_DEINSTALL;
+              old->state_flag |= SF_OBSOLETE;
+         }
+     }
+     return pkg_mark_dependencies_for_installation(conf, new, pkgs_needed);
+}
+
+\f
+
+int satisfy_dependencies_for(opkg_conf_t *conf, pkg_t *pkg)
+{
+     int i, err;
+     pkg_vec_t *depends = pkg_vec_alloc();
+     pkg_t *dep;
+     char **unresolved = NULL;
+     int ndepends;
+
+     ndepends = pkg_hash_fetch_unsatisfied_dependencies(conf, 
+                                                       pkg, depends, 
+                                                       &unresolved);
+
+     if (unresolved) {
+         opkg_message(conf, OPKG_ERROR,
+                      "%s: Cannot satisfy the following dependencies for %s:\n\t",
+                      conf->force_depends ? "Warning" : "ERROR", pkg->name);
+         while (*unresolved) {
+              opkg_message(conf, OPKG_ERROR, " %s", *unresolved);
+              unresolved++;
+         }
+         opkg_message(conf, OPKG_ERROR, "\n");
+         if (! conf->force_depends) {
+              opkg_message(conf, OPKG_INFO,
+                           "This could mean that your package list is out of date or that the packages\n"
+                           "mentioned above do not yet exist (try 'opkg update'). To proceed in spite\n"
+                           "of this problem try again with the '-force-depends' option.\n");
+              pkg_vec_free(depends);
+              return OPKG_PKG_DEPS_UNSATISFIED;
+         }
+     }
+
+     if (ndepends <= 0) {
+         return 0;
+     }
+
+     /* Mark packages as to-be-installed */
+     for (i=0; i < depends->len; i++) {
+         /* Dependencies should be installed the same place as pkg */
+         if (depends->pkgs[i]->dest == NULL) {
+              depends->pkgs[i]->dest = pkg->dest;
+         }
+         depends->pkgs[i]->state_want = SW_INSTALL;
+     }
+
+     for (i = 0; i < depends->len; i++) {
+         dep = depends->pkgs[i];
+         /* The package was uninstalled when we started, but another
+            dep earlier in this loop may have depended on it and pulled
+            it in, so check first. */
+         if ((dep->state_status != SS_INSTALLED)
+             && (dep->state_status != SS_UNPACKED)) {
+               opkg_message(conf, OPKG_DEBUG2,"Function: %s calling opkg_install_pkg \n",__FUNCTION__);
+              err = opkg_install_pkg(conf, dep,0);
+              /* mark this package as having been automatically installed to
+               * satisfy a dependancy */
+              dep->auto_installed = 1;
+              if (err) {
+                   pkg_vec_free(depends);
+                   return err;
+              }
+         }
+     }
+
+     pkg_vec_free(depends);
+
+     return 0;
+}
+
+
+/* check all packages have their dependences satisfied, e.g., in case an upgraded package split */ 
+int opkg_satisfy_all_dependences(opkg_conf_t *conf)
+{
+     if (conf->nodeps == 0) {
+         int i;
+         pkg_vec_t *installed = pkg_vec_alloc();
+         pkg_hash_fetch_all_installed(&conf->pkg_hash, installed);
+         for (i = 0; i < installed->len; i++) {
+              pkg_t *pkg = installed->pkgs[i];
+              satisfy_dependencies_for(conf, pkg);
+         }
+         pkg_vec_free(installed);
+     }
+     return 0;
+}
+
+\f
+
+static int check_conflicts_for(opkg_conf_t *conf, pkg_t *pkg)
+{
+     int i;
+     pkg_vec_t *conflicts = NULL;
+     int level;
+     const char *prefix;
+     if (conf->force_depends) {
+         level = OPKG_NOTICE;
+         prefix = "Warning";
+     } else {
+         level = OPKG_ERROR;
+         prefix = "ERROR";
+     }
+
+     if (!conf->force_depends)
+         conflicts = (pkg_vec_t *)pkg_hash_fetch_conflicts(&conf->pkg_hash, pkg);
+
+     if (conflicts) {
+         opkg_message(conf, level,
+                      "%s: The following packages conflict with %s:\n\t", prefix, pkg->name);
+         i = 0;
+         while (i < conflicts->len)
+              opkg_message(conf, level, " %s", conflicts->pkgs[i++]->name);
+         opkg_message(conf, level, "\n");
+         pkg_vec_free(conflicts);
+         return OPKG_PKG_DEPS_UNSATISFIED;
+     }
+     return 0;
+}
+
+static int update_file_ownership(opkg_conf_t *conf, pkg_t *new_pkg, pkg_t *old_pkg)
+{
+     str_list_t *new_list = pkg_get_installed_files(new_pkg);
+     str_list_elt_t *iter;
+
+     for (iter = new_list->head; iter; iter = iter->next) {
+         char *new_file = iter->data;
+         pkg_t *owner = file_hash_get_file_owner(conf, new_file);
+         if (!new_file)
+              opkg_message(conf, OPKG_ERROR, "Null new_file for new_pkg=%s\n", new_pkg->name);
+         if (!owner || (owner == old_pkg))
+              file_hash_set_file_owner(conf, new_file, new_pkg);
+     }
+     if (old_pkg) {
+         str_list_t *old_list = pkg_get_installed_files(old_pkg);
+         for (iter = old_list->head; iter; iter = iter->next) {
+              char *old_file = iter->data;
+              pkg_t *owner = file_hash_get_file_owner(conf, old_file);
+              if (owner == old_pkg) {
+                   /* obsolete */
+                   hash_table_insert(&conf->obs_file_hash, old_file, old_pkg);
+              }
+         }
+     }
+     return 0;
+}
+
+static int verify_pkg_installable(opkg_conf_t *conf, pkg_t *pkg)
+{
+    /* XXX: FEATURE: Anything else needed here? Maybe a check on free space? */
+
+    /* sma 6.20.02:  yup; here's the first bit */
+    /* 
+     * XXX: BUG easy for cworth
+     * 1) please point the call below to the correct current root destination
+     * 2) we need to resolve how to check the required space for a pending pkg, 
+     *    my diddling with the .ipk file size below isn't going to cut it.
+     * 3) return a proper error code instead of 1
+     */
+     int comp_size, blocks_available;
+    
+     if (!conf->force_space && pkg->installed_size != NULL) {
+         blocks_available = get_available_blocks(conf->default_dest->root_dir);
+
+         comp_size = strtoul(pkg->installed_size, NULL, 0);
+         /* round up a blocks count without doing fancy-but-slow casting jazz */ 
+         comp_size = (int)((comp_size + 1023) / 1024);
+
+         if (comp_size >= blocks_available) {
+              opkg_message(conf, OPKG_ERROR,
+                           "Only have %d available blocks on filesystem %s, pkg %s needs %d\n", 
+                           blocks_available, conf->default_dest->root_dir, pkg->name, comp_size);
+              return ENOSPC;
+         }
+     }
+     return 0;
+}
+
+static int unpack_pkg_control_files(opkg_conf_t *conf, pkg_t *pkg)
+{
+     int err;
+     char *conffiles_file_name;
+     char *root_dir;
+     FILE *conffiles_file;
+
+     sprintf_alloc(&pkg->tmp_unpack_dir, "%s/%s-XXXXXX", conf->tmp_dir, pkg->name);
+
+     pkg->tmp_unpack_dir = mkdtemp(pkg->tmp_unpack_dir);
+     if (pkg->tmp_unpack_dir == NULL) {
+         opkg_message(conf, OPKG_ERROR,
+                      "%s: Failed to create temporary directory '%s': %s\n",
+                      __FUNCTION__, pkg->tmp_unpack_dir, strerror(errno));
+         return errno;
+     }
+
+     err = pkg_extract_control_files_to_dir(pkg, pkg->tmp_unpack_dir);
+     if (err) {
+         return err;
+     }
+
+     /* XXX: CLEANUP: There might be a cleaner place to read in the
+       conffiles. Seems like I should be able to get everything to go
+       through pkg_init_from_file. If so, maybe it would make sense to
+       move all of unpack_pkg_control_files to that function. */
+
+     /* Don't need to re-read conffiles if we already have it */
+     if (pkg->conffiles.head) {
+         return 0;
+     }
+
+     sprintf_alloc(&conffiles_file_name, "%s/conffiles", pkg->tmp_unpack_dir);
+     if (! file_exists(conffiles_file_name)) {
+         free(conffiles_file_name);
+         return 0;
+     }
+    
+     conffiles_file = fopen(conffiles_file_name, "r");
+     if (conffiles_file == NULL) {
+         fprintf(stderr, "%s: failed to open %s: %s\n",
+                 __FUNCTION__, conffiles_file_name, strerror(errno));
+         free(conffiles_file_name);
+         return errno;
+     }
+     free(conffiles_file_name);
+
+     while (1) {
+         char *cf_name;
+         char *cf_name_in_dest;
+
+         cf_name = file_read_line_alloc(conffiles_file);
+         if (cf_name == NULL) {
+              break;
+         }
+         str_chomp(cf_name);
+         if (cf_name[0] == '\0') {
+              continue;
+         }
+
+         /* Prepend dest->root_dir to conffile name.
+            Take pains to avoid multiple slashes. */
+         root_dir = pkg->dest->root_dir;
+         if (conf->offline_root)
+              /* skip the offline_root prefix */
+              root_dir = pkg->dest->root_dir + strlen(conf->offline_root);
+         sprintf_alloc(&cf_name_in_dest, "%s%s", root_dir,
+                       cf_name[0] == '/' ? (cf_name + 1) : cf_name);
+
+         /* Can't get an md5sum now, (file isn't extracted yet).
+            We'll wait until resolve_conffiles */
+         conffile_list_append(&pkg->conffiles, cf_name_in_dest, NULL);
+
+         free(cf_name);
+         free(cf_name_in_dest);
+     }
+
+     fclose(conffiles_file);
+
+     return 0;
+}
+
+/* returns number of installed replacees */
+int pkg_get_installed_replacees(opkg_conf_t *conf, pkg_t *pkg, pkg_vec_t *installed_replacees)
+{
+     abstract_pkg_t **replaces = pkg->replaces;
+     int replaces_count = pkg->replaces_count;
+     int i, j;
+     for (i = 0; i < replaces_count; i++) {
+         abstract_pkg_t *ab_pkg = replaces[i];
+         pkg_vec_t *pkg_vec = ab_pkg->pkgs;
+         if (pkg_vec) {
+              for (j = 0; j < pkg_vec->len; j++) {
+                   pkg_t *replacee = pkg_vec->pkgs[j];
+                   if (!pkg_conflicts(pkg, replacee))
+                        continue;
+                   if (replacee->state_status == SS_INSTALLED) {
+                        pkg_vec_insert(installed_replacees, replacee);
+                   }
+              }
+         }
+     }
+     return installed_replacees->len;
+}
+
+int pkg_remove_installed_replacees(opkg_conf_t *conf, pkg_vec_t *replacees)
+{
+     int i;
+     int replaces_count = replacees->len;
+     for (i = 0; i < replaces_count; i++) {
+         pkg_t *replacee = replacees->pkgs[i];
+         int err;
+         replacee->state_flag |= SF_REPLACE; /* flag it so remove won't complain */
+         err = opkg_remove_pkg(conf, replacee,0);
+         if (err)
+              return err;
+     }
+     return 0;
+}
+
+/* to unwind the removal: make sure they are installed */
+int pkg_remove_installed_replacees_unwind(opkg_conf_t *conf, pkg_vec_t *replacees)
+{
+     int i, err;
+     int replaces_count = replacees->len;
+     for (i = 0; i < replaces_count; i++) {
+         pkg_t *replacee = replacees->pkgs[i];
+         if (replacee->state_status != SS_INSTALLED) {
+               opkg_message(conf, OPKG_DEBUG2,"Function: %s calling opkg_install_pkg \n",__FUNCTION__);
+              err = opkg_install_pkg(conf, replacee,0);
+              if (err)
+                   return err;
+         }
+     }
+     return 0;
+}
+
+int caught_sigint = 0;
+static void opkg_install_pkg_sigint_handler(int sig)
+{
+     caught_sigint = sig;
+}
+
+/* compares versions of pkg and old_pkg, returns 0 if OK to proceed with installation of pkg, 1 otherwise */
+static int opkg_install_check_downgrade(opkg_conf_t *conf, pkg_t *pkg, pkg_t *old_pkg, int message)
+{        
+     if (old_pkg) {
+          char message_out[15];
+         char *old_version = pkg_version_str_alloc(old_pkg);
+         char *new_version = pkg_version_str_alloc(pkg);
+         int cmp = pkg_compare_versions(old_pkg, pkg);
+         int rc = 0;
+
+          memset(message_out,'\x0',15);
+          strncpy (message_out,"Upgrading ",strlen("Upgrading ")); 
+          if ( (conf->force_downgrade==1) && (cmp > 0) ){     /* We've been asked to allow downgrade  and version is precedent */
+             cmp = -1 ;                                       /* then we force opkg to downgrade */ 
+             strncpy (message_out,"Downgrading ",strlen("Downgrading "));         /* We need to use a value < 0 because in the 0 case we are asking to */
+                                                              /* reinstall, and some check could fail asking the "force-reinstall" option */
+          } 
+
+         if (cmp > 0) {
+              opkg_message(conf, OPKG_NOTICE,
+                           "Not downgrading package %s on %s from %s to %s.\n",
+                           old_pkg->name, old_pkg->dest->name, old_version, new_version);
+              rc = 1;
+         } else if (cmp < 0) {
+              opkg_message(conf, OPKG_NOTICE,
+                           "%s%s on %s from %s to %s...\n",
+                           message_out, pkg->name, old_pkg->dest->name, old_version, new_version);
+              pkg->dest = old_pkg->dest;
+              rc = 0;
+         } else /* cmp == 0 */ {
+              if (conf->force_reinstall) {
+                   opkg_message(conf, OPKG_NOTICE,
+                                "Reinstalling %s (%s) on %s...\n",
+                                pkg->name, new_version, old_pkg->dest->name);
+                   pkg->dest = old_pkg->dest;
+                   rc = 0;
+              } else {
+                   opkg_message(conf, OPKG_NOTICE,
+                                "Not installing %s (%s) on %s -- already installed.\n",
+                                pkg->name, new_version, old_pkg->dest->name);
+                   rc = 1;
+              }
+         } 
+         free(old_version);
+         free(new_version);
+         return rc;
+     } else {
+      char message_out[15] ;
+      memset(message_out,'\x0',15);
+      if ( message ) 
+          strncpy( message_out,"Upgrading ",strlen("Upgrading ") );
+      else
+          strncpy( message_out,"Installing ",strlen("Installing ") );
+         char *version = pkg_version_str_alloc(pkg);
+      
+         opkg_message(conf, OPKG_NOTICE,
+                      "%s%s (%s) to %s...\n", message_out,
+                      pkg->name, version, pkg->dest->name);
+         free(version);
+         return 0;
+     }
+}
+
+/* and now the meat... */
+int opkg_install_pkg(opkg_conf_t *conf, pkg_t *pkg, int from_upgrade)
+{
+     int err = 0;
+     int message = 0;
+     pkg_t *old_pkg = NULL;
+     pkg_vec_t *replacees;
+     abstract_pkg_t *ab_pkg = NULL;
+     int old_state_flag;
+     char* file_md5;
+     char *pkgid;
+
+    
+     if ( from_upgrade ) 
+        message = 1;            /* Coming from an upgrade, and should change the output message */
+
+     if (!pkg) {
+         opkg_message(conf, OPKG_ERROR,
+                      "INTERNAL ERROR: null pkg passed to opkg_install_pkg\n");
+         return -EINVAL;
+     }
+
+     opkg_message(conf, OPKG_DEBUG2, "Function: %s calling pkg_arch_supported %s \n", __FUNCTION__, __FUNCTION__);
+
+     if (!pkg_arch_supported(conf, pkg)) {
+         opkg_message(conf, OPKG_ERROR, "INTERNAL ERROR: architecture %s for pkg %s is unsupported.\n",
+                      pkg->architecture, pkg->name);
+         return -EINVAL;
+     }
+     if (pkg->state_status == SS_INSTALLED && conf->force_reinstall == 0 && conf->nodeps == 0) {
+         err = satisfy_dependencies_for(conf, pkg);
+         if (err) { return err; }
+
+         opkg_message(conf, OPKG_NOTICE,
+                      "Package %s is already installed in %s.\n", 
+                      pkg->name, pkg->dest->name);
+         return 0;
+     }
+
+     if (pkg->dest == NULL) {
+         pkg->dest = conf->default_dest;
+     }
+
+     old_pkg = pkg_hash_fetch_installed_by_name(&conf->pkg_hash, pkg->name);
+
+     err = opkg_install_check_downgrade(conf, pkg, old_pkg, message);
+     if (err) { return err; }
+
+     pkg->state_want = SW_INSTALL;
+     if (old_pkg){                          
+         old_pkg->state_want = SW_DEINSTALL; /* needed for check_data_file_clashes of dependences */
+     }
+
+
+     /* Abhaya: conflicts check */
+     err = check_conflicts_for(conf, pkg);
+     if (err) { return err; }
+    
+     /* this setup is to remove the upgrade scenario in the end when
+       installing pkg A, A deps B & B deps on A. So both B and A are
+       installed. Then A's installation is started resulting in an
+       uncecessary upgrade */ 
+     if (pkg->state_status == SS_INSTALLED
+        && conf->force_reinstall == 0) return 0;
+    
+     err = verify_pkg_installable(conf, pkg);
+     if (err) { return err; }
+
+     if (pkg->local_filename == NULL) {
+         err = opkg_download_pkg(conf, pkg, conf->tmp_dir);
+         if (err) {
+              opkg_message(conf, OPKG_ERROR,
+                           "Failed to download %s. Perhaps you need to run 'opkg update'?\n",
+                           pkg->name);
+              return err;
+         }
+     }
+
+/* Check for md5 values */
+     if (pkg->md5sum)
+     {
+         file_md5 = file_md5sum_alloc(pkg->local_filename);
+         if (strcmp(file_md5, pkg->md5sum))
+         {
+              opkg_message(conf, OPKG_ERROR,
+                           "Package %s md5sum mismatch. Either the opkg or the package index are corrupt. Try 'opkg update'.\n",
+                           pkg->name);
+              free(file_md5);
+              return err;
+         }
+         free(file_md5);
+     }
+
+     if (pkg->tmp_unpack_dir == NULL) {
+         unpack_pkg_control_files(conf, pkg);
+     }
+
+     /* We should update the filelist here, so that upgrades of packages that split will not fail. -Jamey 27-MAR-03 */
+/* Pigi: check if it will pass from here when replacing. It seems to fail */
+/* That's rather strange that files don't change owner. Investigate !!!!!!*/
+     err = update_file_ownership(conf, pkg, old_pkg);
+     if (err) { return err; }
+
+     if (conf->nodeps == 0) {
+         err = satisfy_dependencies_for(conf, pkg);
+         if (err) { return err; }
+     }
+
+     replacees = pkg_vec_alloc();
+     pkg_get_installed_replacees(conf, pkg,&n