4 #include <rpm/rpmlog.h>
5 #include <rpm/rpmmacro.h>
6 #include <rpm/rpmfileutil.h>
9 #include "lib/rpmlock.h"
13 /* Internal interface */
15 #define RPMLOCK_PATH LOCALSTATEDIR "/lock/rpm/transaction"
16 static const char * const rpmlock_path_default = "%{?_rpmlock_path}";
17 static const char * rpmlock_path = NULL;
20 RPMLOCK_READ = 1 << 0,
21 RPMLOCK_WRITE = 1 << 1,
22 RPMLOCK_WAIT = 1 << 2,
30 static rpmlock rpmlock_new(const char *rootdir)
32 rpmlock lock = (rpmlock) malloc(sizeof(*lock));
34 /* XXX oneshot to determine path for fcntl lock. */
35 if (rpmlock_path == NULL) {
36 char * t = rpmGenPath(rootdir, rpmlock_path_default, NULL);
37 if (t == NULL || *t == '\0' || *t == '%')
38 t = strdup(RPMLOCK_PATH);
39 rpmlock_path = xstrdup(t);
43 mode_t oldmask = umask(022);
44 lock->fd = open(rpmlock_path, O_RDWR|O_CREAT, 0644);
45 (void) umask(oldmask);
48 lock->fd = open(rpmlock_path, O_RDONLY);
53 lock->openmode = RPMLOCK_READ;
56 lock->openmode = RPMLOCK_WRITE | RPMLOCK_READ;
62 static void rpmlock_free(rpmlock lock)
65 (void) close(lock->fd);
70 static int rpmlock_acquire(rpmlock lock, int mode)
73 if (lock && (mode & lock->openmode)) {
76 if (mode & RPMLOCK_WAIT)
80 if (mode & RPMLOCK_READ)
81 info.l_type = F_RDLCK;
83 info.l_type = F_WRLCK;
84 info.l_whence = SEEK_SET;
88 if (fcntl(lock->fd, cmd, &info) != -1)
94 static void rpmlock_release(rpmlock lock)
98 info.l_type = F_UNLCK;
99 info.l_whence = SEEK_SET;
103 (void) fcntl(lock->fd, F_SETLK, &info);
108 /* External interface */
110 void *rpmtsAcquireLock(rpmts ts)
112 const char *rootDir = rpmtsRootDir(ts);
115 if (!rootDir || rpmtsChrootDone(ts))
117 lock = rpmlock_new(rootDir);
119 rpmlog(RPMLOG_ERR, _("can't create transaction lock on %s\n"), rpmlock_path);
120 } else if (!rpmlock_acquire(lock, RPMLOCK_WRITE)) {
121 if (lock->openmode & RPMLOCK_WRITE)
122 rpmlog(RPMLOG_WARNING,
123 _("waiting for transaction lock on %s\n"), rpmlock_path);
124 if (!rpmlock_acquire(lock, RPMLOCK_WRITE|RPMLOCK_WAIT)) {
126 _("can't create transaction lock on %s\n"), rpmlock_path);
134 void rpmtsFreeLock(void *lock)
136 rpmlock_release((rpmlock)lock); /* Not really needed here. */
137 rpmlock_free((rpmlock)lock);