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.
2) Parameter --force-confnew. Always overwrite config files. 3) Parameter --force-confold. Never overwrite, always create .dpkg-new. Changes for v4: - Long --force-confxxx options instead of non-compatible short ones. - Add long options for --install, --list, etc. Changes for v3: - "Changed by user?" -check added. - -N and -O options added. - Not a config option anymore (because of new default mode). Comments needed: > In the long run, pain from having noncompatible behavior > is worse than pain from one-time conversion for the users > which depend on current behavior. What should we do about -C, -F and -u if LONG_OPTS is not enabled? Real dpkg does not have any short options for them. BusyBox's -C conflicts with real dpkg: -C|--audit Check for broken package(s). 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-24 13:50:20.384479124 +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; @@ -1614,21 +1679,44 @@ int i; enum { OPT_configure = 0x1, - OPT_force_ignore_depends = 0x2, + OPT_force = 0x2, OPT_install = 0x4, OPT_list_installed = 0x8, OPT_purge = 0x10, OPT_remove = 0x20, OPT_unpack = 0x40, + OPT_force_ignore_depends = 0x80, + OPT_force_confnew = 0x100, + OPT_force_confold = 0x200, }; +#if ENABLE_LONG_OPTS + static const char dpkg_longopts[] ALIGN1 = + "configure\0" No_argument "C" + "force\0" Required_argument "F" + "install\0" No_argument "i" + "list\0" No_argument "l" + "purge\0" No_argument "P" + "remove\0" No_argument "r" + "unpack\0" No_argument "u" + "force-depends\0" No_argument "\xff" + "force-confnew\0" No_argument "\xfe" + "force-confold\0" No_argument "\xfd" + ; +#endif INIT_G(); + IF_LONG_OPTS(applet_long_options = dpkg_longopts); opt = getopt32(argv, "CF:ilPru", &str_f); //if (opt & OPT_configure) ... // -C - if (opt & OPT_force_ignore_depends) { // -F (--force in official dpkg) - if (strcmp(str_f, "depends")) - opt &= ~OPT_force_ignore_depends; + if (opt & OPT_force) { // -F (--force in official dpkg) + if (strcmp(str_f, "depends") == 0) + opt |= OPT_force_ignore_depends; + else if (strcmp(str_f, "confnew") == 0) + opt |= OPT_force_confnew; + else if (strcmp(str_f, "confold") == 0) + opt |= OPT_force_confold; + else bb_show_usage(); } //if (opt & OPT_install) ... // -i //if (opt & OPT_list_installed) ... // -l @@ -1748,10 +1836,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-24 12:29:11.176479064 +0200 @@ -926,13 +926,28 @@ #define dpkg_full_usage "\n\n" \ "Install, remove and manage Debian packages\n" \ "\nOptions:" \ + IF_LONG_OPTS( \ + "\n -i,--install Install the package" \ + "\n -l,--list List of installed packages" \ + "\n --configure Configure an unpackaged package" \ + "\n -P,--purge Purge all files of a package" \ + "\n -r,--remove Remove all but the configuration files for a package" \ + "\n --unpack Unpack a package, but don't configure it" \ + "\n --force-depends Ignore dependency problems" \ + "\n --force-confnew Overwrite existing config files when installing" \ + "\n --force-confold Keep old config files when installing" \ + ) \ + IF_NOT_LONG_OPTS( \ "\n -i Install the package" \ "\n -l List of installed packages" \ "\n -C Configure an unpackaged package" \ - "\n -F depends Ignore dependency problems" \ "\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 -F depends Ignore dependency problems" \ + "\n -F confnew Overwrite existing config files when installing" \ + "\n -F confold 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
