The following commit has been merged in the master branch:
commit c3d9eea8d03d93eed6e2d87a97acfca5562b2b32
Author: Guillem Jover <[email protected]>
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 [email protected]
with a subject of "unsubscribe". Trouble? Contact [email protected]