6 #include <rpm/rpmlog.h>
7 #include <rpm/rpmmacro.h>
8 #include <rpm/rpmfileutil.h>
11 #include "lib/rpmlock.h"
15 /* Internal interface */
17 #define RPMLOCK_PATH LOCALSTATEDIR "/lock/rpm/transaction"
18 static const char * const rpmlock_path_default = "%{?_rpmlock_path}";
19 static const char * rpmlock_path = NULL;
22 RPMLOCK_READ = 1 << 0,
23 RPMLOCK_WRITE = 1 << 1,
24 RPMLOCK_WAIT = 1 << 2,
32 static rpmlock rpmlock_new(const char *rootdir)
34 rpmlock lock = (rpmlock) malloc(sizeof(*lock));
36 /* XXX oneshot to determine path for fcntl lock. */
37 if (rpmlock_path == NULL) {
38 char * t = rpmGenPath(rootdir, rpmlock_path_default, NULL);
39 if (t == NULL || *t == '\0' || *t == '%')
40 t = xstrdup(RPMLOCK_PATH);
41 rpmlock_path = xstrdup(t);
42 (void) rpmioMkpath(dirname(t), 0755, getuid(), getgid());
46 mode_t oldmask = umask(022);
47 lock->fd = open(rpmlock_path, O_RDWR|O_CREAT, 0644);
48 (void) umask(oldmask);
51 lock->fd = open(rpmlock_path, O_RDONLY);
56 lock->openmode = RPMLOCK_READ;
59 lock->openmode = RPMLOCK_WRITE | RPMLOCK_READ;
65 static void rpmlock_free(rpmlock lock)
68 (void) close(lock->fd);
73 static int rpmlock_acquire(rpmlock lock, int mode)
76 if (lock && (mode & lock->openmode)) {
79 if (mode & RPMLOCK_WAIT)
83 if (mode & RPMLOCK_READ)
84 info.l_type = F_RDLCK;
86 info.l_type = F_WRLCK;
87 info.l_whence = SEEK_SET;
91 if (fcntl(lock->fd, cmd, &info) != -1)
97 static void rpmlock_release(rpmlock lock)
101 info.l_type = F_UNLCK;
102 info.l_whence = SEEK_SET;
106 (void) fcntl(lock->fd, F_SETLK, &info);
111 /* External interface */
113 void *rpmtsAcquireLock(rpmts ts)
115 const char *rootDir = rpmtsRootDir(ts);
118 if (!rootDir || rpmtsChrootDone(ts))
120 lock = rpmlock_new(rootDir);
123 _("can't create transaction lock on %s (%s)\n"),
124 rpmlock_path, strerror(errno));
125 } else if (!rpmlock_acquire(lock, RPMLOCK_WRITE)) {
126 if (lock->openmode & RPMLOCK_WRITE)
127 rpmlog(RPMLOG_WARNING,
128 _("waiting for transaction lock on %s\n"), rpmlock_path);
129 if (!rpmlock_acquire(lock, RPMLOCK_WRITE|RPMLOCK_WAIT)) {
131 _("can't create transaction lock on %s (%s)\n"),
132 rpmlock_path, strerror(errno));
140 void rpmtsFreeLock(void *lock)
142 rpmlock_release((rpmlock)lock); /* Not really needed here. */
143 rpmlock_free((rpmlock)lock);