Просмотр исходного кода

libdpkg: Refactor the database locking into a general file locking

Make the lockdatabase functions use the lock_files ones instead.

Based on a patch by Ian Jackson <ian@davenant.greenend.org.uk>.
Guillem Jover лет назад: 18
Родитель
Сommit
ac7509f212
3 измененных файлов с 66 добавлено и 18 удалено
  1. 16 0
      ChangeLog
  2. 6 0
      lib/dpkg.h
  3. 44 18
      lib/lock.c

+ 16 - 0
ChangeLog

@@ -1,3 +1,19 @@
+2008-03-25  Ian Jackson  <ian@davenant.greenend.org.uk>,
+            Guillem Jover  <guillem@debian.org>
+
+	* lib/dpkg.h (lock_file): New function prototype.
+	(unlock_file): Likewise.
+	* lib/lock.c (cu_unlockdb): Rename to ...
+	(cu_unlock_file): ... here. Rename dblockfd to lockfd, and take it
+	from argv.
+	(unlock_file): New function.
+	(lock_file): Likewise.
+	(dblockfd): Move variable to ...
+	(lockdatabase): ... here. Call lock_file instead of doing the
+	actual file locking.
+	(unlockdatabase): Call unlock_file, instead if doing the actual
+	pop_cleanup.
+
 2008-03-24  Ian Jackson  <ian@davenant.greenend.org.uk>
 
 	* lib/dpkg.h (error_printer): New function pointer type.

+ 6 - 0
lib/dpkg.h

@@ -214,6 +214,12 @@ void cu_closepipe(int argc, void **argv);
 void cu_closedir(int argc, void **argv);
 void cu_closefd(int argc, void **argv);
 
+/*** lock.c ***/
+
+void lock_file(int *lockfd, const char *filename,
+               const char *emsg, const char *emsg_eagain);
+void unlock_file(void);
+
 /*** from mlib.c ***/
 
 void setcloexec(int fd, const char* fn);

+ 44 - 18
lib/lock.c

@@ -32,26 +32,58 @@
 #include <dpkg.h>
 #include <dpkg-db.h>
 
-static int dblockfd= -1;
-
-static void cu_unlockdb(int argc, void **argv) {
+static void
+cu_unlock_file(int argc, void **argv)
+{
+  int lockfd = *(int*)argv[0];
   struct flock fl;
-  assert(dblockfd >= 0);
+
+  assert(lockfd >= 0);
   fl.l_type= F_UNLCK;
   fl.l_whence= SEEK_SET;
   fl.l_start= 0;
   fl.l_len= 0;
-  if (fcntl(dblockfd,F_SETLK,&fl) == -1)
+  if (fcntl(lockfd, F_SETLK, &fl) == -1)
     ohshite(_("unable to unlock dpkg status database"));
 }
 
+void
+unlock_file(void)
+{
+  pop_cleanup(ehflag_normaltidy); /* Calls cu_unlock_file. */
+}
+
+/* lockfd must be allocated statically as its addresses is passed to
+ * a cleanup handler. */
+void
+lock_file(int *lockfd, const char *filename,
+          const char *emsg, const char *emsg_eagain)
+{
+  struct flock fl;
+
+  setcloexec(*lockfd, filename);
+
+  fl.l_type = F_WRLCK;
+  fl.l_whence = SEEK_SET;
+  fl.l_start = 0;
+  fl.l_len = 0;
+
+  if (fcntl(*lockfd, emsg_eagain ? F_SETLK : F_SETLKW, &fl) == -1) {
+    if (emsg_eagain && (errno == EACCES || errno == EAGAIN))
+      ohshit(emsg_eagain);
+    ohshite(emsg);
+  }
+
+  push_cleanup(cu_unlock_file, ~0, NULL, 0, 1, lockfd);
+}
+
 void unlockdatabase(const char *admindir) {
-  pop_cleanup(ehflag_normaltidy); /* calls cu_unlockdb */
+  unlock_file();
 }
 
 void lockdatabase(const char *admindir) {
+  static int dblockfd = -1;
   int n;
-  struct flock fl;
   char *dblockfile= NULL;
   
     n= strlen(admindir);
@@ -66,16 +98,10 @@ void lockdatabase(const char *admindir) {
       ohshite(_("unable to open/create status database lockfile"));
     }
   }
-  fl.l_type= F_WRLCK;
-  fl.l_whence= SEEK_SET;
-  fl.l_start= 0;
-  fl.l_len= 0;
-  if (fcntl(dblockfd,F_SETLK,&fl) == -1) {
-    if (errno == EACCES || errno == EAGAIN)
-      ohshit(_("status database area is locked by another process"));
-    ohshite(_("unable to lock dpkg status database"));
-  }
-  setcloexec(dblockfd, dblockfile);
+
+  lock_file(&dblockfd, dblockfile,
+            _("unable to lock dpkg status database"),
+            _("status database area is locked by another process"));
+
   free(dblockfile);
-  push_cleanup(cu_unlockdb,~0, NULL,0, 0);
 }