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 <[email protected]>
---
 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

Reply via email to