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>
This commit is contained in:
parent
1d448cff65
commit
3d43aed10c
126
archival/dpkg.c
126
archival/dpkg.c
@ -1308,7 +1308,7 @@ static void list_packages(const char *pattern)
|
||||
name_str = name_hashtable[package_hashtable[status_hashtable[i]->package]->name];
|
||||
vers_str = name_hashtable[package_hashtable[status_hashtable[i]->package]->version];
|
||||
|
||||
if (pattern && fnmatch(pattern, name_str, 0))
|
||||
if (pattern && fnmatch(pattern, name_str, 0) != 0)
|
||||
continue;
|
||||
|
||||
/* get abbreviation for status field 1 */
|
||||
@ -1491,6 +1491,58 @@ static char *deb_extract_control_file_to_buffer(archive_handle_t *ar_handle, lli
|
||||
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 *fp;
|
||||
char *filename, *line;
|
||||
|
||||
filename = xasprintf("/var/lib/dpkg/info/%s.%s", package_name, control_name);
|
||||
fp = fopen_for_read(filename);
|
||||
free(filename);
|
||||
if (fp != NULL) {
|
||||
while ((line = xmalloc_fgetline(fp)) != NULL)
|
||||
llist_add_to(ll, line);
|
||||
fclose(fp);
|
||||
}
|
||||
}
|
||||
|
||||
static char FAST_FUNC filter_rename_config(archive_handle_t *archive_handle)
|
||||
{
|
||||
int 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))
|
||||
return EXIT_SUCCESS; /* no */
|
||||
|
||||
fd = open(name_ptr, O_RDONLY);
|
||||
if (fd >= 0) {
|
||||
md5_ctx_t md5;
|
||||
char *md5line, *buf;
|
||||
int count;
|
||||
|
||||
/* Calculate MD5 of existing file */
|
||||
buf = xmalloc(4096);
|
||||
md5_begin(&md5);
|
||||
while ((count = safe_read(fd, buf, 4096)) > 0)
|
||||
md5_hash(buf, count, &md5);
|
||||
md5_end(buf, &md5); /* using buf as result storage */
|
||||
close(fd);
|
||||
|
||||
md5line = xmalloc(16 * 2 + 2 + strlen(name_ptr) + 1);
|
||||
sprintf(bin2hex(md5line, buf, 16), " %s", name_ptr);
|
||||
free(buf);
|
||||
|
||||
/* 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);
|
||||
}
|
||||
return EXIT_SUCCESS;
|
||||
}
|
||||
|
||||
static void FAST_FUNC data_extract_all_prefix(archive_handle_t *archive_handle)
|
||||
{
|
||||
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)
|
||||
name_ptr++;
|
||||
/* Skip all leading "./" and "../" */
|
||||
while (name_ptr[0] == '.') {
|
||||
if (name_ptr[1] == '.' && name_ptr[2] == '/')
|
||||
if (name_ptr[1] == '.')
|
||||
name_ptr++;
|
||||
if (name_ptr[1] != '/')
|
||||
break;
|
||||
@ -1510,9 +1562,26 @@ static void FAST_FUNC data_extract_all_prefix(archive_handle_t *archive_handle)
|
||||
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) {
|
||||
/* remove .dpkg-new suffix */
|
||||
archive_handle->file_header->name[strlen(archive_handle->file_header->name) - 9] = '\0';
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
enum {
|
||||
OPT_configure = (1 << 0),
|
||||
OPT_force = (1 << 1),
|
||||
OPT_install = (1 << 2),
|
||||
OPT_list_installed = (1 << 3),
|
||||
OPT_purge = (1 << 4),
|
||||
OPT_remove = (1 << 5),
|
||||
OPT_unpack = (1 << 6),
|
||||
OPT_force_ignore_depends = (1 << 7),
|
||||
OPT_force_confnew = (1 << 8),
|
||||
OPT_force_confold = (1 << 9),
|
||||
};
|
||||
|
||||
static void unpack_package(deb_file_t *deb_file)
|
||||
{
|
||||
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)
|
||||
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 (!(option_mask32 & OPT_force_confold))
|
||||
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);
|
||||
@ -1558,9 +1634,15 @@ static void unpack_package(deb_file_t *deb_file)
|
||||
/* Run the preinst prior to extracting */
|
||||
run_package_script_or_die(package_name, "preinst");
|
||||
|
||||
/* Don't overwrite existing config files */
|
||||
if (!(option_mask32 & OPT_force_confnew))
|
||||
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,23 +1696,37 @@ int dpkg_main(int argc UNUSED_PARAM, char **argv)
|
||||
int state_status;
|
||||
int status_num;
|
||||
int i;
|
||||
enum {
|
||||
OPT_configure = 0x1,
|
||||
OPT_force_ignore_depends = 0x2,
|
||||
OPT_install = 0x4,
|
||||
OPT_list_installed = 0x8,
|
||||
OPT_purge = 0x10,
|
||||
OPT_remove = 0x20,
|
||||
OPT_unpack = 0x40,
|
||||
};
|
||||
#if ENABLE_LONG_OPTS
|
||||
static const char dpkg_longopts[] ALIGN1 =
|
||||
// FIXME: we use -C non-compatibly, should be:
|
||||
// "-C|--audit Check for broken package(s)"
|
||||
"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();
|
||||
option_mask32 = opt;
|
||||
}
|
||||
//if (opt & OPT_install) ... // -i
|
||||
//if (opt & OPT_list_installed) ... // -l
|
||||
@ -1639,7 +1735,7 @@ int dpkg_main(int argc UNUSED_PARAM, char **argv)
|
||||
//if (opt & OPT_unpack) ... // -u (--unpack in official dpkg)
|
||||
argv += optind;
|
||||
/* check for non-option argument if expected */
|
||||
if (!opt || (!argv[0] && !(opt && OPT_list_installed)))
|
||||
if (!opt || (!argv[0] && !(opt & OPT_list_installed)))
|
||||
bb_show_usage();
|
||||
|
||||
/* puts("(Reading database ... xxxxx files and directories installed.)"); */
|
||||
|
@ -931,13 +931,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]"
|
||||
|
Loading…
Reference in New Issue
Block a user