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