diff options
author | niemeyer <devnull@localhost> | 2004-02-25 19:54:58 +0000 |
---|---|---|
committer | niemeyer <devnull@localhost> | 2004-02-25 19:54:58 +0000 |
commit | 0f828b95fce2b1f150748e37582dff1d767f6951 (patch) | |
tree | 7e0958c7b4505c5e73619a343296cfa77ad59cd9 | |
parent | c5406814b8c821a715a391764e18a86d0d2aa300 (diff) | |
download | librpm-tizen-0f828b95fce2b1f150748e37582dff1d767f6951.tar.gz librpm-tizen-0f828b95fce2b1f150748e37582dff1d767f6951.tar.bz2 librpm-tizen-0f828b95fce2b1f150748e37582dff1d767f6951.zip |
Creating transaction locking scheme based on fcntl file locking
during writing operations. For now, this system will wait forever
for the lock to be released. This will ensure that current
applications will get the necessary protection without breaking
unexpectedly.
Modified Files:
lib/Makefile.am lib/rpmts.c lib/transaction.c
Added Files:
lib/rpmlock.c lib/rpmlock.h
CVS patchset: 7130
CVS date: 2004/02/25 19:54:58
-rw-r--r-- | lib/Makefile.am | 4 | ||||
-rw-r--r-- | lib/rpmlock.c | 135 | ||||
-rw-r--r-- | lib/rpmlock.h | 7 | ||||
-rw-r--r-- | lib/rpmts.c | 11 | ||||
-rw-r--r-- | lib/transaction.c | 14 |
5 files changed, 167 insertions, 4 deletions
diff --git a/lib/Makefile.am b/lib/Makefile.am index e5bd741d4..317659eba 100644 --- a/lib/Makefile.am +++ b/lib/Makefile.am @@ -20,7 +20,7 @@ pkginc_HEADERS = \ misc.h rpmcli.h rpmlib.h \ rpmal.h rpmds.h rpmfi.h rpmps.h rpmsx.h rpmte.h rpmts.h stringbuf.h noinst_HEADERS = \ - cpio.h fsm.h manifest.h psm.h rpmlead.h signature.h + cpio.h fsm.h manifest.h psm.h rpmlead.h signature.h rpmlock.h mylibs = librpm.la LIBS = @@ -36,7 +36,7 @@ librpm_la_SOURCES = \ rpmal.c rpmchecksig.c rpmds.c rpmfi.c rpminstall.c \ rpmlead.c rpmlibprov.c rpmps.c rpmrc.c rpmsx.c rpmte.c rpmts.c \ rpmvercmp.c signature.c stringbuf.c transaction.c \ - verify.c + verify.c rpmlock.c librpm_la_LDFLAGS = -release 4.3 $(LDFLAGS) \ $(top_builddir)/rpmdb/librpmdb.la \ $(top_builddir)/rpmio/librpmio.la \ diff --git a/lib/rpmlock.c b/lib/rpmlock.c new file mode 100644 index 000000000..65fcf3d66 --- /dev/null +++ b/lib/rpmlock.c @@ -0,0 +1,135 @@ + +#include "system.h" + +#include <sys/types.h> +#include <sys/stat.h> +#include <unistd.h> +#include <fcntl.h> +#include <string.h> + +#include <rpmlib.h> + +#include "rpmts.h" + +#include "rpmlock.h" + +/* Internal interface */ + +#define RPMLOCK_FILE "/var/lib/rpm/transaction.lock" + +enum { + RPMLOCK_READ = 1 << 0, + RPMLOCK_WRITE = 1 << 1, + RPMLOCK_WAIT = 1 << 2, +}; + +typedef struct { + int fd; + int openmode; +} rpmlock; + +static rpmlock *rpmlock_new(const char *rootdir) +{ + rpmlock *lock = (rpmlock *)malloc(sizeof(rpmlock)); + if (lock) { + mode_t oldmask = umask(022); + char *path = (char *)malloc(strlen(rootdir)+ + strlen(RPMLOCK_FILE)); + if (!path) { + free(lock); + return NULL; + } + sprintf(path, "%s/%s", rootdir, RPMLOCK_FILE); + lock->fd = open(RPMLOCK_FILE, O_RDWR|O_CREAT, 0644); + umask(oldmask); + if (lock->fd == -1) { + lock->fd = open(RPMLOCK_FILE, O_RDONLY); + if (lock->fd == -1) { + free(lock); + lock = NULL; + } else { + lock->openmode = RPMLOCK_READ; + } + } else { + lock->openmode = RPMLOCK_WRITE | RPMLOCK_READ; + } + } + return lock; +} + +static void rpmlock_free(rpmlock *lock) +{ + if (lock) { + close(lock->fd); + free(lock); + } +} + +static int rpmlock_acquire(rpmlock *lock, int mode) +{ + int res = 0; + if (lock && (mode & lock->openmode)) { + struct flock info; + int cmd; + if (mode & RPMLOCK_WAIT) + cmd = F_SETLKW; + else + cmd = F_SETLK; + if (mode & RPMLOCK_READ) + info.l_type = F_RDLCK; + else + info.l_type = F_WRLCK; + info.l_whence = SEEK_SET; + info.l_start = 0; + info.l_len = 0; + if (fcntl(lock->fd, cmd, &info) != -1) + res = 1; + } + return res; +} + +static void rpmlock_release(rpmlock *lock) +{ + if (lock) { + struct flock info; + info.l_type = F_UNLCK; + info.l_whence = SEEK_SET; + info.l_start = 0; + info.l_len = 0; + fcntl(lock->fd, F_SETLK, &info); + } +} + + +/* External interface */ + +void *rpmtsAcquireLock(rpmts ts) +{ + const char *rootDir = rpmtsRootDir(ts); + rpmlock *lock; + if (!rootDir) + rootDir = "/"; + lock = rpmlock_new(rootDir); + if (!lock) { + rpmMessage(RPMMESS_ERROR, _("can't create transaction lock\n")); + } else if (!rpmlock_acquire(lock, RPMLOCK_WRITE)) { + if (lock->openmode & RPMLOCK_WRITE) + rpmMessage(RPMMESS_WARNING, + _("waiting for transaction lock\n")); + if (!rpmlock_acquire(lock, RPMLOCK_WRITE|RPMLOCK_WAIT)) { + rpmMessage(RPMMESS_ERROR, + _("can't create transaction lock\n")); + rpmlock_free(lock); + lock = NULL; + } + } + return lock; +} + +void rpmtsFreeLock(void *lock) +{ + rpmlock_release((rpmlock *)lock); /* Not really needed here. */ + rpmlock_free((rpmlock *)lock); +} + + diff --git a/lib/rpmlock.h b/lib/rpmlock.h new file mode 100644 index 000000000..cfd84f764 --- /dev/null +++ b/lib/rpmlock.h @@ -0,0 +1,7 @@ +#ifndef RPMLOCK_H +#define RPMLOCK_H + +void *rpmtsAcquireLock(rpmts ts); +void rpmtsFreeLock(void *lock); + +#endif diff --git a/lib/rpmts.c b/lib/rpmts.c index 1b54ac717..dc2bb8d24 100644 --- a/lib/rpmts.c +++ b/lib/rpmts.c @@ -13,6 +13,7 @@ #include "rpmal.h" #include "rpmds.h" #include "rpmfi.h" +#include "rpmlock.h" #define _RPMTE_INTERNAL /* XXX te->h */ #include "rpmte.h" @@ -168,16 +169,24 @@ int rpmtsOpenDB(rpmts ts, int dbmode) int rpmtsInitDB(rpmts ts, int dbmode) { - return rpmdbInit(ts->rootDir, dbmode); + void *lock = rpmtsAcquireLock(ts); + int rc = -1; + if (lock) + rc = rpmdbInit(ts->rootDir, dbmode); + rpmtsFreeLock(lock); + return rc; } int rpmtsRebuildDB(rpmts ts) { int rc; + void *lock = rpmtsAcquireLock(ts); + if (!lock) return -1; if (!(ts->vsflags & RPMVSF_NOHDRCHK)) rc = rpmdbRebuild(ts->rootDir, ts, headerCheck); else rc = rpmdbRebuild(ts->rootDir, NULL, NULL); + rpmtsFreeLock(lock); return rc; } diff --git a/lib/transaction.c b/lib/transaction.c index 4fdeab547..4bf848637 100644 --- a/lib/transaction.c +++ b/lib/transaction.c @@ -14,6 +14,8 @@ #include "rpmds.h" +#include "rpmlock.h" + #define _RPMFI_INTERNAL #include "rpmfi.h" @@ -957,6 +959,10 @@ int rpmtsRun(rpmts ts, rpmps okProbs, rpmprobFilterFlags ignoreSet) if (rpmtsNElements(ts) <= 0) return -1; + void *lock = rpmtsAcquireLock(ts); + if (!lock) + return -1; + if (rpmtsFlags(ts) & RPMTRANS_FLAG_NOSCRIPTS) (void) rpmtsSetFlags(ts, (rpmtsFlags(ts) | _noTransScripts | _noTransTriggers)); if (rpmtsFlags(ts) & RPMTRANS_FLAG_NOTRIGGERS) @@ -973,8 +979,10 @@ int rpmtsRun(rpmts ts, rpmps okProbs, rpmprobFilterFlags ignoreSet) ? O_RDONLY : (O_RDWR|O_CREAT); /* Open database RDWR for installing packages. */ - if (rpmtsOpenDB(ts, dbmode)) + if (rpmtsOpenDB(ts, dbmode)) { + rpmtsFreeLock(lock); return -1; /* XXX W2DO? */ + } } ts->ignoreSet = ignoreSet; @@ -1194,6 +1202,7 @@ rpmMessage(RPMMESS_DEBUG, _("computing file dispositions\n")); matches = xcalloc(fc, sizeof(*matches)); if (rpmdbFindFpList(rpmtsGetRdb(ts), fi->fps, matches, fc)) { ps = rpmpsFree(ps); + rpmtsFreeLock(lock); return 1; /* XXX WTFO? */ } @@ -1331,6 +1340,7 @@ rpmMessage(RPMMESS_DEBUG, _("computing file dispositions\n")); (okProbs != NULL || rpmpsTrim(ts->probs, okProbs))) ) { + rpmtsFreeLock(lock); return ts->orderCount; } @@ -1546,6 +1556,8 @@ assert(psm != NULL); /*@=branchstate@*/ pi = rpmtsiFree(pi); + rpmtsFreeLock(lock); + /*@-nullstate@*/ /* FIX: ts->flList may be NULL */ if (ourrc) return -1; |