Add macro %isu_package to generate ISU Package
[platform/upstream/rpm.git] / lib / rpmlock.c
1
2 #include "system.h"
3
4 #include <errno.h>
5
6 #include <rpm/rpmlog.h>
7 #include <rpm/rpmfileutil.h>
8
9 #include "lib/rpmlock.h"
10
11 #include "debug.h"
12
13 /* Internal interface */
14
15 enum {
16     RPMLOCK_READ   = 1 << 0,
17     RPMLOCK_WRITE  = 1 << 1,
18     RPMLOCK_WAIT   = 1 << 2,
19 };
20
21 struct rpmlock_s {
22     int fd;
23     int openmode;
24 };
25
26 static rpmlock rpmlock_new(const char *lock_path)
27 {
28     rpmlock lock = (rpmlock) malloc(sizeof(*lock));
29
30     if (lock != NULL) {
31         mode_t oldmask = umask(022);
32         lock->fd = open(lock_path, O_RDWR|O_CREAT, 0644);
33         (void) umask(oldmask);
34
35         if (lock->fd == -1) {
36             lock->fd = open(lock_path, O_RDONLY);
37             if (lock->fd == -1) {
38                 free(lock);
39                 lock = NULL;
40             } else {
41                 lock->openmode = RPMLOCK_READ;
42             }
43         } else {
44             lock->openmode = RPMLOCK_WRITE | RPMLOCK_READ;
45         }
46     }
47     return lock;
48 }
49
50 static void rpmlock_free(rpmlock lock)
51 {
52     if (lock) {
53         (void) close(lock->fd);
54         free(lock);
55     }
56 }
57
58 static int rpmlock_acquire(rpmlock lock, int mode)
59 {
60     int res = 0;
61     if (lock && (mode & lock->openmode)) {
62         struct flock info;
63         int cmd;
64         if (mode & RPMLOCK_WAIT)
65             cmd = F_SETLKW;
66         else
67             cmd = F_SETLK;
68         if (mode & RPMLOCK_READ)
69             info.l_type = F_RDLCK;
70         else
71             info.l_type = F_WRLCK;
72         info.l_whence = SEEK_SET;
73         info.l_start = 0;
74         info.l_len = 0;
75         info.l_pid = 0;
76         if (fcntl(lock->fd, cmd, &info) != -1)
77             res = 1;
78     }
79     return res;
80 }
81
82 static void rpmlock_release(rpmlock lock)
83 {
84     if (lock) {
85         struct flock info;
86         info.l_type = F_UNLCK;
87         info.l_whence = SEEK_SET;
88         info.l_start = 0;
89         info.l_len = 0;
90         info.l_pid = 0;
91         (void) fcntl(lock->fd, F_SETLK, &info);
92      }
93 }
94
95
96 /* External interface */
97
98 rpmlock rpmlockAcquire(const char *lock_path, const char *descr)
99 {
100     rpmlock lock = rpmlock_new(lock_path);
101     if (!lock) {
102         rpmlog(RPMLOG_ERR, _("can't create %s lock on %s (%s)\n"), 
103                 descr, lock_path, strerror(errno));
104     } else if (!rpmlock_acquire(lock, RPMLOCK_WRITE)) {
105         if (lock->openmode & RPMLOCK_WRITE)
106             rpmlog(RPMLOG_WARNING, _("waiting for %s lock on %s\n"),
107                     descr, lock_path);
108         if (!rpmlock_acquire(lock, RPMLOCK_WRITE|RPMLOCK_WAIT)) {
109             rpmlog(RPMLOG_ERR, _("can't create %s lock on %s (%s)\n"), 
110                    descr, lock_path, strerror(errno));
111             rpmlock_free(lock);
112             lock = NULL;
113         }
114     }
115     return lock;
116 }
117
118 rpmlock rpmlockFree(rpmlock lock)
119 {
120     rpmlock_release(lock); /* Not really needed here. */
121     rpmlock_free(lock);
122     return NULL;
123 }
124
125