The following commit has been merged in the master branch:
commit c3d9eea8d03d93eed6e2d87a97acfca5562b2b32
Author: Guillem Jover <guil...@debian.org>
Date:   Fri Jul 2 13:13:01 2010 +0200

    dpkg: Detect locked databases on --audit
    
    Detect when another process has locked the database, and mention that
    problematic dpkg --audit results might be due to ongoing operations.
    
    Closes: #80252

diff --git a/debian/changelog b/debian/changelog
index ae1c951..a2d130e 100644
--- a/debian/changelog
+++ b/debian/changelog
@@ -68,6 +68,9 @@ dpkg (1.15.8) UNRELEASED; urgency=low
     packages.
   * Move Dpkg.pm and Dpkg/Gettext.pm from dpkg to libdpkg-perl.
   * Bump Standards-Version to 3.9.0.
+  * Detect when another process has locked the database, and mention that
+    problematic dpkg --audit results might be due to ongoing operations.
+    Closes: #80252
 
   [ Updated programs translations ]
   * Catalan (Guillem Jover).
diff --git a/lib/dpkg/dbmodify.c b/lib/dpkg/dbmodify.c
index 02c1c35..bc39448 100644
--- a/lib/dpkg/dbmodify.c
+++ b/lib/dpkg/dbmodify.c
@@ -142,10 +142,40 @@ static const struct fni {
   {   NULL, NULL                                      }
 };
 
+static int dblockfd = -1;
+
+bool
+modstatdb_is_locked(const char *admindir)
+{
+  struct varbuf lockfile = VARBUF_INIT;
+  int lockfd;
+  bool locked;
+
+  varbufprintf(&lockfile, "%s/%s", admindir, LOCKFILE);
+
+  if (dblockfd == -1) {
+    lockfd = open(lockfile.buf, O_RDONLY);
+    if (lockfd == -1)
+      ohshite(_("unable to open lock file %s for testing"), lockfile.buf);
+  } else {
+    lockfd = dblockfd;
+  }
+
+  locked = file_is_locked(lockfd, lockfile.buf);
+
+  /* We only close the file if there was no lock open, otherwise we would
+   * release the existing lock on close. */
+  if (dblockfd == -1)
+    close(lockfd);
+
+  varbuf_destroy(&lockfile);
+
+  return locked;
+}
+
 void
 modstatdb_lock(const char *admindir)
 {
-  static int dblockfd = -1;
   int n;
   char *dblockfile = NULL;
 
diff --git a/lib/dpkg/dpkg-db.h b/lib/dpkg/dpkg-db.h
index c2e57a4..3590d42 100644
--- a/lib/dpkg/dpkg-db.h
+++ b/lib/dpkg/dpkg-db.h
@@ -199,6 +199,7 @@ enum modstatdb_rw {
   msdbrw_noavail= 0100,
 };
 
+bool modstatdb_is_locked(const char *admindir);
 void modstatdb_lock(const char *admindir);
 void modstatdb_unlock(void);
 enum modstatdb_rw modstatdb_init(const char *admindir, enum modstatdb_rw 
reqrwflags);
diff --git a/lib/dpkg/file.c b/lib/dpkg/file.c
index 12a67f2..40fbbea 100644
--- a/lib/dpkg/file.c
+++ b/lib/dpkg/file.c
@@ -83,6 +83,28 @@ file_unlock(void)
        pop_cleanup(ehflag_normaltidy); /* Calls file_unlock_cleanup. */
 }
 
+/**
+ * Check if a file has a lock acquired.
+ *
+ * @param lockfd The file descriptor for the lock.
+ * @param filename The file name associated to the file descriptor.
+ */
+bool
+file_is_locked(int lockfd, const char *filename)
+{
+       struct flock fl;
+
+       file_lock_setup(&fl, F_WRLCK);
+
+       if (fcntl(lockfd, F_GETLK, &fl) == -1)
+               ohshit(_("unable to check file '%s' lock status"), filename);
+
+       if (fl.l_type == F_WRLCK && fl.l_pid != getpid())
+               return true;
+       else
+               return false;
+}
+
 /* lockfd must be allocated statically as its addresses is passed to
  * a cleanup handler. */
 void
diff --git a/lib/dpkg/file.h b/lib/dpkg/file.h
index ee14206..24dca2c 100644
--- a/lib/dpkg/file.h
+++ b/lib/dpkg/file.h
@@ -21,6 +21,8 @@
 #ifndef LIBDPKG_FILE_H
 #define LIBDPKG_FILE_H
 
+#include <stdbool.h>
+
 #include <dpkg/macros.h>
 
 DPKG_BEGIN_DECLS
@@ -30,6 +32,7 @@ DPKG_BEGIN_DECLS
  */
 void file_copy_perms(const char *src, const char *dst);
 
+bool file_is_locked(int lockfd, const char *filename);
 void file_lock(int *lockfd, const char *filename,
                const char *emsg, const char *emsg_eagain);
 void file_unlock(void);
diff --git a/src/enquiry.c b/src/enquiry.c
index af45426..d8e1a4f 100644
--- a/src/enquiry.c
+++ b/src/enquiry.c
@@ -124,6 +124,7 @@ static void describebriefly(struct pkginfo *pkg) {
 
 void audit(const char *const *argv) {
   const struct badstatinfo *bsi;
+  bool head_running = false;
 
   if (*argv)
     badusage(_("--%s takes no arguments"), cipaction->olong);
@@ -138,6 +139,13 @@ void audit(const char *const *argv) {
     it= iterpkgstart(); 
     while ((pkg= iterpkgnext(it))) {
       if (!bsi->yesno(pkg,bsi)) continue;
+      if (!head_running) {
+        if (modstatdb_is_locked(admindir))
+          puts(_(
+"Another process has locked the database for writing, and might currently be\n"
+"modifying it, some of the following problems might just be due to that.\n"));
+        head_running = true;
+      }
       if (!head) {
         fputs(gettext(bsi->explanation),stdout);
         head = true;

-- 
dpkg's main repository


-- 
To UNSUBSCRIBE, email to debian-dpkg-cvs-requ...@lists.debian.org
with a subject of "unsubscribe". Trouble? Contact listmas...@lists.debian.org

Reply via email to