Skip to content

Commit 06fb419

Browse files
committed
lib: lock pkgdb using a separate file
this is done to avoid losing the lock when the packackage database is replaced with a new file (during updates).
1 parent e8d14ce commit 06fb419

File tree

2 files changed

+52
-65
lines changed

2 files changed

+52
-65
lines changed

include/xbps.h.in

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -50,7 +50,7 @@
5050
*
5151
* This header documents the full API for the XBPS Library.
5252
*/
53-
#define XBPS_API_VERSION "20250521"
53+
#define XBPS_API_VERSION "20250629"
5454

5555
#ifndef XBPS_VERSION
5656
#define XBPS_VERSION "UNSET"
@@ -571,6 +571,10 @@ struct xbps_handle {
571571
* in the configuration file.
572572
*/
573573
xbps_array_t repositories;
574+
/**
575+
* @private
576+
*/
577+
int lock_fd;
574578
/**
575579
* @private
576580
*/

lib/pkgdb.c

Lines changed: 47 additions & 64 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@
2323
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
2424
*/
2525

26+
#include <sys/file.h>
2627
#include <sys/types.h>
2728
#include <sys/stat.h>
2829

@@ -61,84 +62,69 @@
6162
* data type is specified on its edge, i.e array, bool, integer, string,
6263
* dictionary.
6364
*/
64-
static int pkgdb_fd = -1;
65-
static bool pkgdb_map_names_done = false;
6665

6766
int
6867
xbps_pkgdb_lock(struct xbps_handle *xhp)
6968
{
69+
char path[PATH_MAX];
7070
mode_t prev_umask;
71-
int rv = 0;
72-
/*
73-
* Use a mandatory file lock to only allow one writer to pkgdb,
74-
* other writers will block.
75-
*/
71+
int r = 0;
72+
73+
if (access(xhp->rootdir, W_OK) == -1 && errno != ENOENT) {
74+
return xbps_error_errno(errno,
75+
"failed to check whether the roodir is wriable: "
76+
"%s: %s\n",
77+
xhp->rootdir, strerror(errno));
78+
}
79+
80+
if (xbps_path_join(path, sizeof(path), xhp->metadir, "lock", (char *)NULL) == -1) {
81+
return xbps_error_errno(errno,
82+
"failed to create lockfile path: %s\n", strerror(errno));
83+
}
84+
7685
prev_umask = umask(022);
77-
xhp->pkgdb_plist = xbps_xasprintf("%s/%s", xhp->metadir, XBPS_PKGDB);
78-
if (xbps_pkgdb_init(xhp) == ENOENT) {
79-
/* if metadir does not exist, create it */
80-
if (access(xhp->metadir, R_OK|X_OK) == -1) {
81-
if (errno != ENOENT) {
82-
rv = errno;
83-
goto ret;
84-
}
85-
if (xbps_mkpath(xhp->metadir, 0755) == -1) {
86-
rv = errno;
87-
xbps_dbg_printf("[pkgdb] failed to create metadir "
88-
"%s: %s\n", xhp->metadir, strerror(rv));
89-
goto ret;
90-
}
86+
87+
/* if metadir does not exist, create it */
88+
if (access(xhp->metadir, R_OK|X_OK) == -1) {
89+
if (errno != ENOENT) {
90+
umask(prev_umask);
91+
return xbps_error_errno(errno,
92+
"failed to check access to metadir: %s: %s\n",
93+
xhp->metadir, strerror(-r));
9194
}
92-
/* if pkgdb is unexistent, create it with an empty dictionary */
93-
xhp->pkgdb = xbps_dictionary_create();
94-
if (!xbps_dictionary_externalize_to_file(xhp->pkgdb, xhp->pkgdb_plist)) {
95-
rv = errno;
96-
xbps_dbg_printf("[pkgdb] failed to create pkgdb "
97-
"%s: %s\n", xhp->pkgdb_plist, strerror(rv));
98-
goto ret;
95+
if (xbps_mkpath(xhp->metadir, 0755) == -1 && errno != EEXIST) {
96+
umask(prev_umask);
97+
return xbps_error_errno(errno,
98+
"failed to create metadir: %s: %s\n",
99+
xhp->metadir, strerror(errno));
99100
}
100101
}
101102

102-
if ((pkgdb_fd = open(xhp->pkgdb_plist, O_CREAT|O_RDWR|O_CLOEXEC, 0664)) == -1) {
103-
rv = errno;
104-
xbps_dbg_printf("[pkgdb] cannot open pkgdb for locking "
105-
"%s: %s\n", xhp->pkgdb_plist, strerror(rv));
106-
free(xhp->pkgdb_plist);
107-
goto ret;
103+
xhp->lock_fd = open(path, O_CREAT|O_WRONLY|O_CLOEXEC, 0664);
104+
if (xhp->lock_fd == -1) {
105+
return xbps_error_errno(errno,
106+
"failed to create lock file: %s: %s\n", path,
107+
strerror(errno));
108108
}
109+
umask(prev_umask);
109110

110-
/*
111-
* If we've acquired the file lock, then pkgdb is writable.
112-
*/
113-
if (lockf(pkgdb_fd, F_TLOCK, 0) == -1) {
114-
rv = errno;
115-
xbps_dbg_printf("[pkgdb] cannot lock pkgdb: %s\n", strerror(rv));
116-
}
117-
/*
118-
* Check if rootdir is writable.
119-
*/
120-
if (access(xhp->rootdir, W_OK) == -1) {
121-
rv = errno;
122-
xbps_dbg_printf("[pkgdb] rootdir %s: %s\n", xhp->rootdir, strerror(rv));
111+
if (flock(xhp->lock_fd, LOCK_EX) == -1) {
112+
close(xhp->lock_fd);
113+
xhp->lock_fd = -1;
114+
return xbps_error_errno(errno, "failed to lock file: %s: %s\n",
115+
path, strerror(errno));
123116
}
124117

125-
ret:
126-
umask(prev_umask);
127-
return rv;
118+
return 0;
128119
}
129120

130121
void
131-
xbps_pkgdb_unlock(struct xbps_handle *xhp UNUSED)
122+
xbps_pkgdb_unlock(struct xbps_handle *xhp)
132123
{
133-
xbps_dbg_printf("%s: pkgdb_fd %d\n", __func__, pkgdb_fd);
134-
135-
if (pkgdb_fd != -1) {
136-
if (lockf(pkgdb_fd, F_ULOCK, 0) == -1)
137-
xbps_dbg_printf("[pkgdb] failed to unlock pkgdb: %s\n", strerror(errno));
138-
139-
(void)close(pkgdb_fd);
140-
pkgdb_fd = -1;
141-
}
124+
if (xhp->lock_fd == -1)
125+
return;
126+
close(xhp->lock_fd);
127+
xhp->lock_fd = -1;
142128
}
143129

144130
static int
@@ -240,7 +226,7 @@ pkgdb_map_names(struct xbps_handle *xhp)
240226
xbps_object_t obj;
241227
int rv = 0;
242228

243-
if (pkgdb_map_names_done || !xbps_dictionary_count(xhp->pkgdb))
229+
if (!xbps_dictionary_count(xhp->pkgdb))
244230
return 0;
245231

246232
/*
@@ -269,9 +255,6 @@ pkgdb_map_names(struct xbps_handle *xhp)
269255
}
270256
}
271257
xbps_object_iterator_release(iter);
272-
if (!rv) {
273-
pkgdb_map_names_done = true;
274-
}
275258
return rv;
276259
}
277260

0 commit comments

Comments
 (0)