rpm  5.4.15
rpmlock.c
Go to the documentation of this file.
1 #include "system.h"
2 
3 #include <rpmio.h>
4 #include <rpmiotypes.h> /* XXX fnpyKey */
5 #include <rpmlog.h>
6 #include <rpmmacro.h>
7 #include <rpmtypes.h>
8 #include <rpmtag.h>
9 
10 #include "rpmts.h"
11 #include "rpmlock.h"
12 
13 #include "debug.h"
14 
15 /*@unchecked@*/ /*@observer@*/
16 static const char * rpmlock_path_default = "%{?_rpmlock_path}";
17 /*@unchecked@*/ /*@only@*/ /*null@*/
18 static const char * rpmlock_path = NULL;
19 
20 enum {
21  RPMLOCK_READ = 1 << 0,
22  RPMLOCK_WRITE = 1 << 1,
23  RPMLOCK_WAIT = 1 << 2,
24 };
25 
26 typedef struct {
27  int fd;
28  int omode;
29 } * rpmlock;
30 
31 #ifdef __cplusplus
32 GENfree(rpmlock)
33 #endif /* __cplusplus */
34 
35 /*@null@*/
36 static int rpmlock_new(/*@unused@*/ const char *rootdir, /*@null@*/ rpmlock *lockp)
37  /*@globals rpmlock_path, rpmGlobalMacroContext, h_errno,
38  fileSystem, internalState @*/
39  /*@modifies *lockp, rpmlock_path, rpmGlobalMacroContext, h_errno,
40  fileSystem, internalState @*/
41 {
42  static int oneshot = 0;
43  rpmlock lock = (rpmlock) xmalloc(sizeof(*lock));
44  int rc = -1;
45 
46  if (lockp)
47  *lockp = NULL;
48 
49  /* XXX oneshot to determine path for fcntl lock. */
50  /* XXX rpmlock_path is set once, cannot be changed with %{_rpmlock_path}. */
51  if (!oneshot) {
52  const char * t = NULL;
53  char * check = rpmExpand(rpmlock_path_default, NULL);
54  if (check[0] != '\0')
55  t = rpmGenPath(rootdir, rpmlock_path_default, NULL);
56  check = _free(check);
57 
58  if (t == NULL || *t == '\0' || *t == '%')
59  t = _free(t);
60  rpmlock_path = t;
61  oneshot++;
62  }
63 
64  if (rpmlock_path != NULL) {
65  mode_t oldmask = umask(022);
66  lock->fd = open(rpmlock_path, O_RDWR|O_CREAT, 0644);
67  (void) umask(oldmask);
68 
69  if (lock->fd == -1) {
70  lock->fd = open(rpmlock_path, O_RDONLY);
71  if (lock->fd == -1)
72  rc = -1;
73  else
74  lock->omode = RPMLOCK_READ;
75  } else
77  rc = 0;
78  }
79  if (rc == 0 && lockp != NULL)
80  *lockp = lock;
81  else
82  lock = _free(lock);
83 /*@-compdef@*/ /*@-nullstate@*/ /*@-globstate@*/
84  return rc;
85 /*@=compdef@*/ /*@=nullstate@*/ /*@=globstate@*/
86 }
87 
88 static rpmlock rpmlock_free(/*@only@*/ /*@null@*/ rpmlock lock)
89  /*@globals fileSystem, internalState @*/
90  /*@modifies lock, fileSystem, internalState @*/
91 {
92  if (lock != NULL) {
93  if (lock->fd > 0)
94  (void) close(lock->fd);
95  lock = _free(lock);
96  }
97  return NULL;
98 }
99 
100 static int rpmlock_acquire(/*@null@*/ rpmlock lock, int mode)
101  /*@*/
102 {
103  int rc = 0;
104 
105  if (lock != NULL && (mode & lock->omode)) {
106  struct flock info;
107  int cmd;
108  if (mode & RPMLOCK_WAIT)
109  cmd = F_SETLKW;
110  else
111  cmd = F_SETLK;
112  if (mode & RPMLOCK_READ)
113  info.l_type = F_RDLCK;
114  else
115  info.l_type = F_WRLCK;
116  info.l_whence = SEEK_SET;
117  info.l_start = 0;
118  info.l_len = 0;
119  info.l_pid = 0;
120  if (fcntl(lock->fd, cmd, &info) != -1)
121  rc = 1;
122  }
123  return rc;
124 }
125 
126 static int rpmlock_release(/*@null@*/ rpmlock lock)
127  /*@globals internalState @*/
128  /*@modifies internalState @*/
129 {
130  int rc = 0;
131 
132  if (lock != NULL) {
133  struct flock info;
134  info.l_type = F_UNLCK;
135  info.l_whence = SEEK_SET;
136  info.l_start = 0;
137  info.l_len = 0;
138  info.l_pid = 0;
139  rc = fcntl(lock->fd, F_SETLK, &info);
140  }
141  return rc;
142 }
143 
145 {
146  const char *rootDir = rpmtsRootDir(ts);
147  rpmlock lock = NULL;
148  int rc;
149 
150  if (rootDir == NULL || rpmtsChrootDone(ts))
151  rootDir = "/";
152  rc = rpmlock_new(rootDir, &lock);
153  if (rc) {
154  if (rpmlock_path != NULL && strcmp(rpmlock_path, rootDir))
156  _("can't create transaction lock on %s (%s)\n"),
157  rpmlock_path, strerror(errno));
158  } else if (lock != NULL) {
159  if (!rpmlock_acquire(lock, RPMLOCK_WRITE)) {
160  if (lock->omode & RPMLOCK_WRITE)
162  _("waiting for transaction lock on %s\n"), rpmlock_path);
164  if (rpmlock_path != NULL && strcmp(rpmlock_path, rootDir))
166  _("can't create transaction lock on %s (%s)\n"),
167  rpmlock_path, strerror(errno));
168  lock = rpmlock_free(lock);
169  }
170  }
171  }
172 /*@-globstate@*/ /* rpmlock_path may be NULL. */
173  return lock;
174 /*@=globstate@*/
175 }
176 
177 void * rpmtsFreeLock(void *lock)
178 {
179  (void) rpmlock_release((rpmlock)lock); /* Not really needed here. */
180  lock = rpmlock_free((rpmlock)lock);
181  return NULL;
182 }
const char bson_timestamp_t * ts
Definition: bson.h:1004
int omode
Definition: rpmlock.c:28
const char * rpmtsRootDir(rpmts ts)
Get transaction rootDir, i.e.
Definition: rpmts.c:903
const char const char * cmd
Definition: mongo.h:777
void * rpmtsFreeLock(void *lock)
Definition: rpmlock.c:177
int errno
static void rpmlog(int code, const char *fmt,...)
Definition: rpmlog.h:299
Yet Another syslog(3) API clone.
static const char * rpmlock_path_default
Definition: rpmlock.c:16
const char * mode
Definition: mongo.h:440
static rpmlock rpmlock_free(rpmlock lock)
Definition: rpmlock.c:88
const char * rpmGenPath(const char *urlroot, const char *urlmdir, const char *urlfile)
Merge 3 args into path, any or all of which may be a url.
Definition: macro.c:3489
int rpmtsChrootDone(rpmts ts)
Get chrootDone flag, i.e.
Definition: rpmts.c:1007
static int rpmlock_new(const char *rootdir, rpmlock *lockp)
Definition: rpmlock.c:36
static int rpmlock_release(rpmlock lock)
Definition: rpmlock.c:126
char * rpmExpand(const char *arg,...)
Return (malloc'ed) concatenated macro expansion(s).
Definition: macro.c:3250
static const char * rpmlock_path
Definition: rpmlock.c:18
#define SEEK_SET
Definition: system.h:226
struct rpmts_s * rpmts
The RPM Transaction Set.
Definition: rpmtypes.h:14
static void * _free(const void *p)
Wrapper to free(3), hides const compilation noise, permit NULL, return NULL.
Definition: rpmiotypes.h:756
Structures and prototypes used for an "rpmts" transaction set.
void * rpmtsAcquireLock(rpmts ts)
Definition: rpmlock.c:144
int fd
Definition: rpmlock.c:27
#define _(Text)
Definition: system.h:29
#define xmalloc
Definition: system.h:32
static int rpmlock_acquire(rpmlock lock, int mode)
Definition: rpmlock.c:100