Oops, missing include for dirname()
[platform/upstream/rpm.git] / lib / rpmlock.c
1
2 #include "system.h"
3
4 #include <libgen.h>
5
6 #include <rpm/rpmlog.h>
7 #include <rpm/rpmmacro.h>
8 #include <rpm/rpmfileutil.h>
9 #include <rpm/rpmts.h>
10
11 #include "lib/rpmlock.h"
12
13 #include "debug.h"
14
15 /* Internal interface */
16
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;
20
21 enum {
22     RPMLOCK_READ   = 1 << 0,
23     RPMLOCK_WRITE  = 1 << 1,
24     RPMLOCK_WAIT   = 1 << 2,
25 };
26
27 typedef struct {
28     int fd;
29     int openmode;
30 } * rpmlock;
31
32 static rpmlock rpmlock_new(const char *rootdir)
33 {
34     rpmlock lock = (rpmlock) malloc(sizeof(*lock));
35
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());
43         t = _free(t);
44     }
45     if (lock != NULL) {
46         mode_t oldmask = umask(022);
47         lock->fd = open(rpmlock_path, O_RDWR|O_CREAT, 0644);
48         (void) umask(oldmask);
49
50         if (lock->fd == -1) {
51             lock->fd = open(rpmlock_path, O_RDONLY);
52             if (lock->fd == -1) {
53                 free(lock);
54                 lock = NULL;
55             } else {
56                 lock->openmode = RPMLOCK_READ;
57             }
58         } else {
59             lock->openmode = RPMLOCK_WRITE | RPMLOCK_READ;
60         }
61     }
62     return lock;
63 }
64
65 static void rpmlock_free(rpmlock lock)
66 {
67     if (lock) {
68         (void) close(lock->fd);
69         free(lock);
70     }
71 }
72
73 static int rpmlock_acquire(rpmlock lock, int mode)
74 {
75     int res = 0;
76     if (lock && (mode & lock->openmode)) {
77         struct flock info;
78         int cmd;
79         if (mode & RPMLOCK_WAIT)
80             cmd = F_SETLKW;
81         else
82             cmd = F_SETLK;
83         if (mode & RPMLOCK_READ)
84             info.l_type = F_RDLCK;
85         else
86             info.l_type = F_WRLCK;
87         info.l_whence = SEEK_SET;
88         info.l_start = 0;
89         info.l_len = 0;
90         info.l_pid = 0;
91         if (fcntl(lock->fd, cmd, &info) != -1)
92             res = 1;
93     }
94     return res;
95 }
96
97 static void rpmlock_release(rpmlock lock)
98 {
99     if (lock) {
100         struct flock info;
101         info.l_type = F_UNLCK;
102         info.l_whence = SEEK_SET;
103         info.l_start = 0;
104         info.l_len = 0;
105         info.l_pid = 0;
106         (void) fcntl(lock->fd, F_SETLK, &info);
107      }
108 }
109
110
111 /* External interface */
112
113 void *rpmtsAcquireLock(rpmts ts)
114 {
115     const char *rootDir = rpmtsRootDir(ts);
116     rpmlock lock;
117
118     if (!rootDir || rpmtsChrootDone(ts))
119         rootDir = "/";
120     lock = rpmlock_new(rootDir);
121     if (!lock) {
122         rpmlog(RPMLOG_ERR, 
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)) {
130             rpmlog(RPMLOG_ERR,
131                    _("can't create transaction lock on %s (%s)\n"), 
132                    rpmlock_path, strerror(errno));
133             rpmlock_free(lock);
134             lock = NULL;
135         }
136     }
137     return lock;
138 }
139
140 void rpmtsFreeLock(void *lock)
141 {
142     rpmlock_release((rpmlock)lock); /* Not really needed here. */
143     rpmlock_free((rpmlock)lock);
144 }
145
146