diff options
author | Kim B. Heino <Kim.Heino@bluegiga.com> | 2010-03-29 14:18:27 +0200 |
---|---|---|
committer | Denys Vlasenko <vda.linux@googlemail.com> | 2010-03-29 14:18:27 +0200 |
commit | 3d43aed10c94bfcfc4a85b9b66bc60c18d22c2b1 (patch) | |
tree | fbd69052583642b77e9436ec6fc11a1461042afb | |
parent | 1d448cff653a9a68f6320d01c9f0505385aa38bd (diff) | |
download | busybox-w32-3d43aed10c94bfcfc4a85b9b66bc60c18d22c2b1.tar.gz busybox-w32-3d43aed10c94bfcfc4a85b9b66bc60c18d22c2b1.tar.bz2 busybox-w32-3d43aed10c94bfcfc4a85b9b66bc60c18d22c2b1.zip |
dpkg: support config file overwrite options
function old new delta
filter_rename_config - 244 +244
static.dpkg_longopts - 112 +112
dpkg_main 3901 3980 +79
unpack_package 515 587 +72
append_control_file_to_llist - 72 +72
data_extract_all_prefix 88 116 +28
------------------------------------------------------------------------------
(add/remove: 3/0 grow/shrink: 3/0 up/down: 607/0) Total: 607 bytes
Signed-off-by: Kim B. Heino <Kim.Heino@bluegiga.com>
Signed-off-by: Denys Vlasenko <vda.linux@googlemail.com>
-rw-r--r-- | archival/dpkg.c | 126 | ||||
-rw-r--r-- | include/usage.h | 17 |
2 files changed, 127 insertions, 16 deletions
diff --git a/archival/dpkg.c b/archival/dpkg.c index 7187ad6a0..befb91d6a 100644 --- a/archival/dpkg.c +++ b/archival/dpkg.c | |||
@@ -1308,7 +1308,7 @@ static void list_packages(const char *pattern) | |||
1308 | name_str = name_hashtable[package_hashtable[status_hashtable[i]->package]->name]; | 1308 | name_str = name_hashtable[package_hashtable[status_hashtable[i]->package]->name]; |
1309 | vers_str = name_hashtable[package_hashtable[status_hashtable[i]->package]->version]; | 1309 | vers_str = name_hashtable[package_hashtable[status_hashtable[i]->package]->version]; |
1310 | 1310 | ||
1311 | if (pattern && fnmatch(pattern, name_str, 0)) | 1311 | if (pattern && fnmatch(pattern, name_str, 0) != 0) |
1312 | continue; | 1312 | continue; |
1313 | 1313 | ||
1314 | /* get abbreviation for status field 1 */ | 1314 | /* get abbreviation for status field 1 */ |
@@ -1491,6 +1491,58 @@ static char *deb_extract_control_file_to_buffer(archive_handle_t *ar_handle, lli | |||
1491 | return ar_handle->dpkg__sub_archive->dpkg__buffer; | 1491 | return ar_handle->dpkg__sub_archive->dpkg__buffer; |
1492 | } | 1492 | } |
1493 | 1493 | ||
1494 | static void append_control_file_to_llist(const char *package_name, const char *control_name, llist_t **ll) | ||
1495 | { | ||
1496 | FILE *fp; | ||
1497 | char *filename, *line; | ||
1498 | |||
1499 | filename = xasprintf("/var/lib/dpkg/info/%s.%s", package_name, control_name); | ||
1500 | fp = fopen_for_read(filename); | ||
1501 | free(filename); | ||
1502 | if (fp != NULL) { | ||
1503 | while ((line = xmalloc_fgetline(fp)) != NULL) | ||
1504 | llist_add_to(ll, line); | ||
1505 | fclose(fp); | ||
1506 | } | ||
1507 | } | ||
1508 | |||
1509 | static char FAST_FUNC filter_rename_config(archive_handle_t *archive_handle) | ||
1510 | { | ||
1511 | int fd; | ||
1512 | char *name_ptr = archive_handle->file_header->name + 1; | ||
1513 | |||
1514 | /* Is this file marked as config file? */ | ||
1515 | if (!find_list_entry(archive_handle->accept, name_ptr)) | ||
1516 | return EXIT_SUCCESS; /* no */ | ||
1517 | |||
1518 | fd = open(name_ptr, O_RDONLY); | ||
1519 | if (fd >= 0) { | ||
1520 | md5_ctx_t md5; | ||
1521 | char *md5line, *buf; | ||
1522 | int count; | ||
1523 | |||
1524 | /* Calculate MD5 of existing file */ | ||
1525 | buf = xmalloc(4096); | ||
1526 | md5_begin(&md5); | ||
1527 | while ((count = safe_read(fd, buf, 4096)) > 0) | ||
1528 | md5_hash(buf, count, &md5); | ||
1529 | md5_end(buf, &md5); /* using buf as result storage */ | ||
1530 | close(fd); | ||
1531 | |||
1532 | md5line = xmalloc(16 * 2 + 2 + strlen(name_ptr) + 1); | ||
1533 | sprintf(bin2hex(md5line, buf, 16), " %s", name_ptr); | ||
1534 | free(buf); | ||
1535 | |||
1536 | /* Is it changed after install? */ | ||
1537 | if (find_list_entry(archive_handle->accept, md5line) == NULL) { | ||
1538 | printf("Warning: Creating %s as %s.dpkg-new\n", name_ptr, name_ptr); | ||
1539 | archive_handle->file_header->name = xasprintf("%s.dpkg-new", archive_handle->file_header->name); | ||
1540 | } | ||
1541 | free(md5line); | ||
1542 | } | ||
1543 | return EXIT_SUCCESS; | ||
1544 | } | ||
1545 | |||
1494 | static void FAST_FUNC data_extract_all_prefix(archive_handle_t *archive_handle) | 1546 | static void FAST_FUNC data_extract_all_prefix(archive_handle_t *archive_handle) |
1495 | { | 1547 | { |
1496 | char *name_ptr = archive_handle->file_header->name; | 1548 | char *name_ptr = archive_handle->file_header->name; |
@@ -1500,7 +1552,7 @@ static void FAST_FUNC data_extract_all_prefix(archive_handle_t *archive_handle) | |||
1500 | name_ptr++; | 1552 | name_ptr++; |
1501 | /* Skip all leading "./" and "../" */ | 1553 | /* Skip all leading "./" and "../" */ |
1502 | while (name_ptr[0] == '.') { | 1554 | while (name_ptr[0] == '.') { |
1503 | if (name_ptr[1] == '.' && name_ptr[2] == '/') | 1555 | if (name_ptr[1] == '.') |
1504 | name_ptr++; | 1556 | name_ptr++; |
1505 | if (name_ptr[1] != '/') | 1557 | if (name_ptr[1] != '/') |
1506 | break; | 1558 | break; |
@@ -1510,9 +1562,26 @@ static void FAST_FUNC data_extract_all_prefix(archive_handle_t *archive_handle) | |||
1510 | if (name_ptr[0] != '\0') { | 1562 | if (name_ptr[0] != '\0') { |
1511 | archive_handle->file_header->name = xasprintf("%s%s", archive_handle->dpkg__buffer, name_ptr); | 1563 | archive_handle->file_header->name = xasprintf("%s%s", archive_handle->dpkg__buffer, name_ptr); |
1512 | data_extract_all(archive_handle); | 1564 | data_extract_all(archive_handle); |
1565 | if (fnmatch("*.dpkg-new", archive_handle->file_header->name, 0) == 0) { | ||
1566 | /* remove .dpkg-new suffix */ | ||
1567 | archive_handle->file_header->name[strlen(archive_handle->file_header->name) - 9] = '\0'; | ||
1568 | } | ||
1513 | } | 1569 | } |
1514 | } | 1570 | } |
1515 | 1571 | ||
1572 | enum { | ||
1573 | OPT_configure = (1 << 0), | ||
1574 | OPT_force = (1 << 1), | ||
1575 | OPT_install = (1 << 2), | ||
1576 | OPT_list_installed = (1 << 3), | ||
1577 | OPT_purge = (1 << 4), | ||
1578 | OPT_remove = (1 << 5), | ||
1579 | OPT_unpack = (1 << 6), | ||
1580 | OPT_force_ignore_depends = (1 << 7), | ||
1581 | OPT_force_confnew = (1 << 8), | ||
1582 | OPT_force_confold = (1 << 9), | ||
1583 | }; | ||
1584 | |||
1516 | static void unpack_package(deb_file_t *deb_file) | 1585 | static void unpack_package(deb_file_t *deb_file) |
1517 | { | 1586 | { |
1518 | const char *package_name = name_hashtable[package_hashtable[deb_file->package]->name]; | 1587 | const char *package_name = name_hashtable[package_hashtable[deb_file->package]->name]; |
@@ -1523,14 +1592,21 @@ static void unpack_package(deb_file_t *deb_file) | |||
1523 | archive_handle_t *archive_handle; | 1592 | archive_handle_t *archive_handle; |
1524 | FILE *out_stream; | 1593 | FILE *out_stream; |
1525 | llist_t *accept_list; | 1594 | llist_t *accept_list; |
1595 | llist_t *conffile_list; | ||
1526 | int i; | 1596 | int i; |
1527 | 1597 | ||
1528 | /* If existing version, remove it first */ | 1598 | /* If existing version, remove it first */ |
1599 | conffile_list = NULL; | ||
1529 | if (strcmp(name_hashtable[get_status(status_num, 3)], "installed") == 0) { | 1600 | if (strcmp(name_hashtable[get_status(status_num, 3)], "installed") == 0) { |
1530 | /* Package is already installed, remove old version first */ | 1601 | /* Package is already installed, remove old version first */ |
1531 | printf("Preparing to replace %s %s (using %s)...\n", package_name, | 1602 | printf("Preparing to replace %s %s (using %s)...\n", package_name, |
1532 | name_hashtable[package_hashtable[status_package_num]->version], | 1603 | name_hashtable[package_hashtable[status_package_num]->version], |
1533 | deb_file->filename); | 1604 | deb_file->filename); |
1605 | |||
1606 | /* Read md5sums from old package */ | ||
1607 | if (!(option_mask32 & OPT_force_confold)) | ||
1608 | append_control_file_to_llist(package_name, "md5sums", &conffile_list); | ||
1609 | |||
1534 | remove_package(status_package_num, 0); | 1610 | remove_package(status_package_num, 0); |
1535 | } else { | 1611 | } else { |
1536 | printf("Unpacking %s (from %s)...\n", package_name, deb_file->filename); | 1612 | printf("Unpacking %s (from %s)...\n", package_name, deb_file->filename); |
@@ -1558,9 +1634,15 @@ static void unpack_package(deb_file_t *deb_file) | |||
1558 | /* Run the preinst prior to extracting */ | 1634 | /* Run the preinst prior to extracting */ |
1559 | run_package_script_or_die(package_name, "preinst"); | 1635 | run_package_script_or_die(package_name, "preinst"); |
1560 | 1636 | ||
1637 | /* Don't overwrite existing config files */ | ||
1638 | if (!(option_mask32 & OPT_force_confnew)) | ||
1639 | append_control_file_to_llist(package_name, "conffiles", &conffile_list); | ||
1640 | |||
1561 | /* Extract data.tar.gz to the root directory */ | 1641 | /* Extract data.tar.gz to the root directory */ |
1562 | archive_handle = init_archive_deb_ar(deb_file->filename); | 1642 | archive_handle = init_archive_deb_ar(deb_file->filename); |
1563 | init_archive_deb_data(archive_handle); | 1643 | init_archive_deb_data(archive_handle); |
1644 | archive_handle->dpkg__sub_archive->accept = conffile_list; | ||
1645 | archive_handle->dpkg__sub_archive->filter = filter_rename_config; | ||
1564 | archive_handle->dpkg__sub_archive->action_data = data_extract_all_prefix; | 1646 | archive_handle->dpkg__sub_archive->action_data = data_extract_all_prefix; |
1565 | archive_handle->dpkg__sub_archive->dpkg__buffer = (char*)"/"; /* huh? */ | 1647 | archive_handle->dpkg__sub_archive->dpkg__buffer = (char*)"/"; /* huh? */ |
1566 | archive_handle->dpkg__sub_archive->ah_flags |= ARCHIVE_UNLINK_OLD; | 1648 | archive_handle->dpkg__sub_archive->ah_flags |= ARCHIVE_UNLINK_OLD; |
@@ -1614,23 +1696,37 @@ int dpkg_main(int argc UNUSED_PARAM, char **argv) | |||
1614 | int state_status; | 1696 | int state_status; |
1615 | int status_num; | 1697 | int status_num; |
1616 | int i; | 1698 | int i; |
1617 | enum { | 1699 | #if ENABLE_LONG_OPTS |
1618 | OPT_configure = 0x1, | 1700 | static const char dpkg_longopts[] ALIGN1 = |
1619 | OPT_force_ignore_depends = 0x2, | 1701 | // FIXME: we use -C non-compatibly, should be: |
1620 | OPT_install = 0x4, | 1702 | // "-C|--audit Check for broken package(s)" |
1621 | OPT_list_installed = 0x8, | 1703 | "configure\0" No_argument "C" |
1622 | OPT_purge = 0x10, | 1704 | "force\0" Required_argument "F" |
1623 | OPT_remove = 0x20, | 1705 | "install\0" No_argument "i" |
1624 | OPT_unpack = 0x40, | 1706 | "list\0" No_argument "l" |
1625 | }; | 1707 | "purge\0" No_argument "P" |
1708 | "remove\0" No_argument "r" | ||
1709 | "unpack\0" No_argument "u" | ||
1710 | "force-depends\0" No_argument "\xff" | ||
1711 | "force-confnew\0" No_argument "\xfe" | ||
1712 | "force-confold\0" No_argument "\xfd" | ||
1713 | ; | ||
1714 | #endif | ||
1626 | 1715 | ||
1627 | INIT_G(); | 1716 | INIT_G(); |
1628 | 1717 | ||
1718 | IF_LONG_OPTS(applet_long_options = dpkg_longopts); | ||
1629 | opt = getopt32(argv, "CF:ilPru", &str_f); | 1719 | opt = getopt32(argv, "CF:ilPru", &str_f); |
1630 | //if (opt & OPT_configure) ... // -C | 1720 | //if (opt & OPT_configure) ... // -C |
1631 | if (opt & OPT_force_ignore_depends) { // -F (--force in official dpkg) | 1721 | if (opt & OPT_force) { // -F (--force in official dpkg) |
1632 | if (strcmp(str_f, "depends")) | 1722 | if (strcmp(str_f, "depends") == 0) |
1633 | opt &= ~OPT_force_ignore_depends; | 1723 | opt |= OPT_force_ignore_depends; |
1724 | else if (strcmp(str_f, "confnew") == 0) | ||
1725 | opt |= OPT_force_confnew; | ||
1726 | else if (strcmp(str_f, "confold") == 0) | ||
1727 | opt |= OPT_force_confold; | ||
1728 | else bb_show_usage(); | ||
1729 | option_mask32 = opt; | ||
1634 | } | 1730 | } |
1635 | //if (opt & OPT_install) ... // -i | 1731 | //if (opt & OPT_install) ... // -i |
1636 | //if (opt & OPT_list_installed) ... // -l | 1732 | //if (opt & OPT_list_installed) ... // -l |
@@ -1639,7 +1735,7 @@ int dpkg_main(int argc UNUSED_PARAM, char **argv) | |||
1639 | //if (opt & OPT_unpack) ... // -u (--unpack in official dpkg) | 1735 | //if (opt & OPT_unpack) ... // -u (--unpack in official dpkg) |
1640 | argv += optind; | 1736 | argv += optind; |
1641 | /* check for non-option argument if expected */ | 1737 | /* check for non-option argument if expected */ |
1642 | if (!opt || (!argv[0] && !(opt && OPT_list_installed))) | 1738 | if (!opt || (!argv[0] && !(opt & OPT_list_installed))) |
1643 | bb_show_usage(); | 1739 | bb_show_usage(); |
1644 | 1740 | ||
1645 | /* puts("(Reading database ... xxxxx files and directories installed.)"); */ | 1741 | /* puts("(Reading database ... xxxxx files and directories installed.)"); */ |
diff --git a/include/usage.h b/include/usage.h index 8b026b43a..cf576c666 100644 --- a/include/usage.h +++ b/include/usage.h | |||
@@ -931,13 +931,28 @@ | |||
931 | #define dpkg_full_usage "\n\n" \ | 931 | #define dpkg_full_usage "\n\n" \ |
932 | "Install, remove and manage Debian packages\n" \ | 932 | "Install, remove and manage Debian packages\n" \ |
933 | "\nOptions:" \ | 933 | "\nOptions:" \ |
934 | IF_LONG_OPTS( \ | ||
935 | "\n -i,--install Install the package" \ | ||
936 | "\n -l,--list List of installed packages" \ | ||
937 | "\n --configure Configure an unpackaged package" \ | ||
938 | "\n -P,--purge Purge all files of a package" \ | ||
939 | "\n -r,--remove Remove all but the configuration files for a package" \ | ||
940 | "\n --unpack Unpack a package, but don't configure it" \ | ||
941 | "\n --force-depends Ignore dependency problems" \ | ||
942 | "\n --force-confnew Overwrite existing config files when installing" \ | ||
943 | "\n --force-confold Keep old config files when installing" \ | ||
944 | ) \ | ||
945 | IF_NOT_LONG_OPTS( \ | ||
934 | "\n -i Install the package" \ | 946 | "\n -i Install the package" \ |
935 | "\n -l List of installed packages" \ | 947 | "\n -l List of installed packages" \ |
936 | "\n -C Configure an unpackaged package" \ | 948 | "\n -C Configure an unpackaged package" \ |
937 | "\n -F depends Ignore dependency problems" \ | ||
938 | "\n -P Purge all files of a package" \ | 949 | "\n -P Purge all files of a package" \ |
939 | "\n -r Remove all but the configuration files for a package" \ | 950 | "\n -r Remove all but the configuration files for a package" \ |
940 | "\n -u Unpack a package, but don't configure it" \ | 951 | "\n -u Unpack a package, but don't configure it" \ |
952 | "\n -F depends Ignore dependency problems" \ | ||
953 | "\n -F confnew Overwrite existing config files when installing" \ | ||
954 | "\n -F confold Keep old config files when installing" \ | ||
955 | ) | ||
941 | 956 | ||
942 | #define dpkg_deb_trivial_usage \ | 957 | #define dpkg_deb_trivial_usage \ |
943 | "[-cefxX] FILE [argument]" | 958 | "[-cefxX] FILE [argument]" |