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

Reply via email to