From: Guillem Jover Date: Tue, 25 Mar 2008 02:37:45 +0000 (+0200) Subject: libdpkg: Refactor the database locking into a general file locking X-Git-Url: https://err.no/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=ac7509f212599818cd262e113928f927a9aff5d2;p=dpkg 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 . --- diff --git a/ChangeLog b/ChangeLog index 233db45a..18da5cf6 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,19 @@ +2008-03-25 Ian Jackson , + Guillem Jover + + * 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 * lib/dpkg.h (error_printer): New function pointer type. diff --git a/lib/dpkg.h b/lib/dpkg.h index 4a53d92e..45967432 100644 --- a/lib/dpkg.h +++ b/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); diff --git a/lib/lock.c b/lib/lock.c index 06fb413e..5d8e3c0c 100644 --- a/lib/lock.c +++ b/lib/lock.c @@ -32,26 +32,58 @@ #include #include -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); }