summaryrefslogtreecommitdiff
path: root/lib/rpmlock.c
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 /lib/rpmlock.c
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
Diffstat (limited to 'lib/rpmlock.c')
-rw-r--r--lib/rpmlock.c135
1 files changed, 135 insertions, 0 deletions
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);
+}
+
+