This patch changes how dpkg handles config files. There are three modes: 1) If config file is unchanged by user then it will be overwritten. If changed, then new config file will be created as configfile.dpkg-new. This is how "real dpkg" handles config files.
This is the default mode. "Real dpkg" parameter: --force-confdef 2) Parameter -N. Always overwrite config files. "Real dpkg" parameter: --force-confnew 3) Parameter -O. Never overwrite, always create .dpkg-new. "Real dpkg" parameter: --force-confold This is version 3 of this patch. Changes: - "Changed by user?" -check added. - -N and -O options added. - Not a config option anymore (because of default mode). Comments needed: Currently BusyBox-dpkg overwrites config files (new option -N). This patch changes default action to match "real dpkg". Is this change allowed? Signed-off-by: Kim B. Heino <[email protected]> diff -ur busybox-1.16.0/archival/dpkg.c dpkg/archival/dpkg.c --- busybox-1.16.0/archival/dpkg.c 2010-01-25 02:59:38.000000000 +0200 +++ dpkg/archival/dpkg.c 2010-03-17 15:59:32.052479524 +0200 @@ -1489,6 +1489,56 @@ return ar_handle->dpkg__sub_archive->dpkg__buffer; } +static void append_control_file_to_llist(const char *package_name, const char *control_name, llist_t **ll) +{ + FILE *fd; + char *filename, *line; + + filename = xasprintf("/var/lib/dpkg/info/%s.%s", package_name, control_name); + if ((fd = fopen_for_read(filename)) != NULL) { + while ((line = xmalloc_fgetline(fd)) != NULL) + llist_add_to(ll, line); + fclose(fd); + } + free(filename); +} + +static char FAST_FUNC filter_rename_config(archive_handle_t *archive_handle) +{ + FILE *fd; + char *name_ptr = archive_handle->file_header->name + 1; + + /* Is this file marked as config file? */ + if (find_list_entry(archive_handle->accept, name_ptr) && + (fd = fopen_for_read(name_ptr)) != NULL) { + md5_ctx_t md5; + char *md5line, *buf; + int count; + + /* Calculate MD5 of existing file */ + buf = xmalloc(4096); + md5_begin(&md5); + while ((count = fread(buf, 1, 4096, fd)) > 0) + md5_hash(buf, count, &md5); + md5_end(buf, &md5); + fclose(fd); + + md5line = xmalloc(16 * 2 + 2 + strlen(name_ptr) + 1); + bin2hex(md5line, buf, 16); + sprintf(md5line + 16 * 2, " %s", name_ptr); + + /* Is it changed after install? */ + if (find_list_entry(archive_handle->accept, md5line) == NULL) { + printf("Warning: Creating %s as %s.dpkg-new\n", name_ptr, name_ptr); + archive_handle->file_header->name = xasprintf("%s.dpkg-new", archive_handle->file_header->name); + } + + free(md5line); + free(buf); + } + return EXIT_SUCCESS; +} + static void FAST_FUNC data_extract_all_prefix(archive_handle_t *archive_handle) { char *name_ptr = archive_handle->file_header->name; @@ -1508,10 +1558,12 @@ if (name_ptr[0] != '\0') { archive_handle->file_header->name = xasprintf("%s%s", archive_handle->dpkg__buffer, name_ptr); data_extract_all(archive_handle); + if (fnmatch("*.dpkg-new", archive_handle->file_header->name, 0) == 0) + archive_handle->file_header->name[strlen(archive_handle->file_header->name) - 9] = 0; } } -static void unpack_package(deb_file_t *deb_file) +static void unpack_package(deb_file_t *deb_file, int force_confnew, int force_confold) { const char *package_name = name_hashtable[package_hashtable[deb_file->package]->name]; const unsigned status_num = search_status_hashtable(package_name); @@ -1521,14 +1573,21 @@ archive_handle_t *archive_handle; FILE *out_stream; llist_t *accept_list; + llist_t *conffile_list; int i; /* If existing version, remove it first */ + conffile_list = NULL; if (strcmp(name_hashtable[get_status(status_num, 3)], "installed") == 0) { /* Package is already installed, remove old version first */ printf("Preparing to replace %s %s (using %s)...\n", package_name, name_hashtable[package_hashtable[status_package_num]->version], deb_file->filename); + + /* Read md5sums from old package */ + if (force_confold == 0) + append_control_file_to_llist(package_name, "md5sums", &conffile_list); + remove_package(status_package_num, 0); } else { printf("Unpacking %s (from %s)...\n", package_name, deb_file->filename); @@ -1556,9 +1615,15 @@ /* Run the preinst prior to extracting */ run_package_script_or_die(package_name, "preinst"); + /* Don't overwrite existing config files */ + if (force_confnew == 0) + append_control_file_to_llist(package_name, "conffiles", &conffile_list); + /* Extract data.tar.gz to the root directory */ archive_handle = init_archive_deb_ar(deb_file->filename); init_archive_deb_data(archive_handle); + archive_handle->dpkg__sub_archive->accept = conffile_list; + archive_handle->dpkg__sub_archive->filter = filter_rename_config; archive_handle->dpkg__sub_archive->action_data = data_extract_all_prefix; archive_handle->dpkg__sub_archive->dpkg__buffer = (char*)"/"; /* huh? */ archive_handle->dpkg__sub_archive->ah_flags |= ARCHIVE_UNLINK_OLD; @@ -1620,11 +1685,13 @@ OPT_purge = 0x10, OPT_remove = 0x20, OPT_unpack = 0x40, + OPT_force_confnew = 0x80, + OPT_force_confold = 0x100, }; INIT_G(); - opt = getopt32(argv, "CF:ilPru", &str_f); + opt = getopt32(argv, "CF:ilPruNO", &str_f); //if (opt & OPT_configure) ... // -C if (opt & OPT_force_ignore_depends) { // -F (--force in official dpkg) if (strcmp(str_f, "depends")) @@ -1748,10 +1815,10 @@ purge_package(deb_file[i]->package); } else if (opt & OPT_unpack) { - unpack_package(deb_file[i]); + unpack_package(deb_file[i], opt & OPT_force_confnew, opt & OPT_force_confold); } else if (opt & OPT_install) { - unpack_package(deb_file[i]); + unpack_package(deb_file[i], opt & OPT_force_confnew, opt & OPT_force_confold); /* package is configured in second pass below */ } else if (opt & OPT_configure) { diff -ur busybox-1.16.0/include/usage.h dpkg/include/usage.h --- busybox-1.16.0/include/usage.h 2010-01-25 02:59:38.000000000 +0200 +++ dpkg/include/usage.h 2010-03-17 16:08:01.169729006 +0200 @@ -922,7 +922,7 @@ "\n -d unix2dos" \ #define dpkg_trivial_usage \ - "[-ilCPru] [-F option] package_name" + "[-ilCPruNO] [-F option] package_name" #define dpkg_full_usage "\n\n" \ "Install, remove and manage Debian packages\n" \ "\nOptions:" \ @@ -933,6 +933,8 @@ "\n -P Purge all files of a package" \ "\n -r Remove all but the configuration files for a package" \ "\n -u Unpack a package, but don't configure it" \ + "\n -N Overwrite existing config files when installing" \ + "\n -O Keep old config files when installing" \ #define dpkg_deb_trivial_usage \ "[-cefxX] FILE [argument]" _______________________________________________ busybox mailing list [email protected] http://lists.busybox.net/mailman/listinfo/busybox
