[pacman-dev] [PATCH] extract db files with dbonly

Andrew Gregory andrew.gregory.8 at gmail.com
Tue Dec 6 06:30:42 UTC 2016


Some database files (install, mtree, and changelog) are extracted
directly from the package, but DBONLY was skipping extraction
altogether, causing those files to be missing after the transaction.

Fixes #52052

Signed-off-by: Andrew Gregory <andrew.gregory.8 at gmail.com>
---
 lib/libalpm/add.c                           | 112 +++++++++++++++-------------
 test/pacman/tests/TESTS                     |   1 +
 test/pacman/tests/dbonly-extracted-files.py |  16 ++++
 3 files changed, 78 insertions(+), 51 deletions(-)
 create mode 100644 test/pacman/tests/dbonly-extracted-files.py

diff --git a/lib/libalpm/add.c b/lib/libalpm/add.c
index d132e52..6501b68 100644
--- a/lib/libalpm/add.c
+++ b/lib/libalpm/add.c
@@ -405,6 +405,10 @@ static int commit_single_pkg(alpm_handle_t *handle, alpm_pkg_t *newpkg,
 	alpm_event_package_operation_t event;
 	const char *log_msg = "adding";
 	const char *pkgfile;
+	struct archive *archive;
+	struct archive_entry *entry;
+	int fd, cwdfd;
+	struct stat buf;
 
 	ASSERT(trans != NULL, return -1);
 
@@ -477,39 +481,44 @@ static int commit_single_pkg(alpm_handle_t *handle, alpm_pkg_t *newpkg,
 		goto cleanup;
 	}
 
-	if(!(trans->flags & ALPM_TRANS_FLAG_DBONLY)) {
-		struct archive *archive;
-		struct archive_entry *entry;
-		struct stat buf;
-		int fd, cwdfd;
-
-		_alpm_log(handle, ALPM_LOG_DEBUG, "extracting files\n");
+	fd = _alpm_open_archive(db->handle, pkgfile, &buf,
+			&archive, ALPM_ERR_PKG_OPEN);
+	if(fd < 0) {
+		ret = -1;
+		goto cleanup;
+	}
 
-		fd = _alpm_open_archive(db->handle, pkgfile, &buf,
-				&archive, ALPM_ERR_PKG_OPEN);
-		if(fd < 0) {
-			ret = -1;
-			goto cleanup;
-		}
+	/* save the cwd so we can restore it later */
+	OPEN(cwdfd, ".", O_RDONLY | O_CLOEXEC);
+	if(cwdfd < 0) {
+		_alpm_log(handle, ALPM_LOG_ERROR, _("could not get current working directory\n"));
+	}
 
-		/* save the cwd so we can restore it later */
-		OPEN(cwdfd, ".", O_RDONLY | O_CLOEXEC);
-		if(cwdfd < 0) {
-			_alpm_log(handle, ALPM_LOG_ERROR, _("could not get current working directory\n"));
+	/* libarchive requires this for extracting hard links */
+	if(chdir(handle->root) != 0) {
+		_alpm_log(handle, ALPM_LOG_ERROR, _("could not change directory to %s (%s)\n"),
+				handle->root, strerror(errno));
+		_alpm_archive_read_free(archive);
+		if(cwdfd >= 0) {
+			close(cwdfd);
 		}
+		close(fd);
+		ret = -1;
+		goto cleanup;
+	}
 
-		/* libarchive requires this for extracting hard links */
-		if(chdir(handle->root) != 0) {
-			_alpm_log(handle, ALPM_LOG_ERROR, _("could not change directory to %s (%s)\n"),
-					handle->root, strerror(errno));
-			_alpm_archive_read_free(archive);
-			if(cwdfd >= 0) {
-				close(cwdfd);
+	if(trans->flags & ALPM_TRANS_FLAG_DBONLY) {
+		_alpm_log(handle, ALPM_LOG_DEBUG, "extracting db files\n");
+		while(archive_read_next_header(archive, &entry) == ARCHIVE_OK) {
+			const char *entryname = archive_entry_pathname(entry);
+			if(entryname[0] == '.') {
+				errors += extract_db_file(handle, archive, entry, newpkg, entryname);
+			} else {
+				archive_read_data_skip(archive);
 			}
-			close(fd);
-			ret = -1;
-			goto cleanup;
 		}
+	} else {
+		_alpm_log(handle, ALPM_LOG_DEBUG, "extracting files\n");
 
 		/* call PROGRESS once with 0 percent, as we sort-of skip that here */
 		PROGRESS(handle, progress, newpkg->name, 0, pkg_count, pkg_current);
@@ -535,33 +544,34 @@ static int commit_single_pkg(alpm_handle_t *handle, alpm_pkg_t *newpkg,
 			/* extract the next file from the archive */
 			errors += extract_single_file(handle, archive, entry, newpkg, oldpkg);
 		}
-		_alpm_archive_read_free(archive);
-		close(fd);
+	}
 
-		/* restore the old cwd if we have it */
-		if(cwdfd >= 0) {
-			if(fchdir(cwdfd) != 0) {
-				_alpm_log(handle, ALPM_LOG_ERROR,
-						_("could not restore working directory (%s)\n"), strerror(errno));
-			}
-			close(cwdfd);
+	_alpm_archive_read_free(archive);
+	close(fd);
+
+	/* restore the old cwd if we have it */
+	if(cwdfd >= 0) {
+		if(fchdir(cwdfd) != 0) {
+			_alpm_log(handle, ALPM_LOG_ERROR,
+					_("could not restore working directory (%s)\n"), strerror(errno));
 		}
+		close(cwdfd);
+	}
 
-		if(errors) {
-			ret = -1;
-			if(is_upgrade) {
-				_alpm_log(handle, ALPM_LOG_ERROR, _("problem occurred while upgrading %s\n"),
-						newpkg->name);
-				alpm_logaction(handle, ALPM_CALLER_PREFIX,
-						"error: problem occurred while upgrading %s\n",
-						newpkg->name);
-			} else {
-				_alpm_log(handle, ALPM_LOG_ERROR, _("problem occurred while installing %s\n"),
-						newpkg->name);
-				alpm_logaction(handle, ALPM_CALLER_PREFIX,
-						"error: problem occurred while installing %s\n",
-						newpkg->name);
-			}
+	if(errors) {
+		ret = -1;
+		if(is_upgrade) {
+			_alpm_log(handle, ALPM_LOG_ERROR, _("problem occurred while upgrading %s\n"),
+					newpkg->name);
+			alpm_logaction(handle, ALPM_CALLER_PREFIX,
+					"error: problem occurred while upgrading %s\n",
+					newpkg->name);
+		} else {
+			_alpm_log(handle, ALPM_LOG_ERROR, _("problem occurred while installing %s\n"),
+					newpkg->name);
+			alpm_logaction(handle, ALPM_CALLER_PREFIX,
+					"error: problem occurred while installing %s\n",
+					newpkg->name);
 		}
 	}
 
diff --git a/test/pacman/tests/TESTS b/test/pacman/tests/TESTS
index 2d87796..cfe50d2 100644
--- a/test/pacman/tests/TESTS
+++ b/test/pacman/tests/TESTS
@@ -11,6 +11,7 @@ TESTS += test/pacman/tests/database002.py
 TESTS += test/pacman/tests/database010.py
 TESTS += test/pacman/tests/database011.py
 TESTS += test/pacman/tests/database012.py
+TESTS += test/pacman/tests/dbonly-extracted-files.py
 TESTS += test/pacman/tests/depconflict100.py
 TESTS += test/pacman/tests/depconflict110.py
 TESTS += test/pacman/tests/depconflict111.py
diff --git a/test/pacman/tests/dbonly-extracted-files.py b/test/pacman/tests/dbonly-extracted-files.py
new file mode 100644
index 0000000..a1bc48d
--- /dev/null
+++ b/test/pacman/tests/dbonly-extracted-files.py
@@ -0,0 +1,16 @@
+import util
+import os.path
+
+self.description = "Install a package with dbonly"
+
+sp = pmpkg("foobar", "1-1")
+sp.files = ["bin/foobar"]
+sp.install['post_install'] = "echo foobar"
+self.addpkg2db("sync", sp)
+
+self.args = "-S --dbonly %s" % sp.name
+
+self.addrule("PACMAN_RETCODE=0")
+self.addrule("PKG_EXIST=foobar")
+self.addrule("FILE_EXIST=%s" % os.path.join(util.PM_DBPATH, "local/foobar-1-1/install"))
+self.addrule("!FILE_EXIST=bin/foobar")
-- 
2.10.2


More information about the pacman-dev mailing list