summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorniemeyer <devnull@localhost>2004-02-25 19:54:58 +0000
committerniemeyer <devnull@localhost>2004-02-25 19:54:58 +0000
commit0f828b95fce2b1f150748e37582dff1d767f6951 (patch)
tree7e0958c7b4505c5e73619a343296cfa77ad59cd9
parentc5406814b8c821a715a391764e18a86d0d2aa300 (diff)
downloadlibrpm-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.am4
-rw-r--r--lib/rpmlock.c135
-rw-r--r--lib/rpmlock.h7
-rw-r--r--lib/rpmts.c11
-rw-r--r--lib/transaction.c14
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;