aboutsummaryrefslogtreecommitdiffstats
path: root/src/libutil
diff options
context:
space:
mode:
Diffstat (limited to 'src/libutil')
-rw-r--r--src/libutil/rrd.c70
-rw-r--r--src/libutil/rrd.h1
2 files changed, 58 insertions, 13 deletions
diff --git a/src/libutil/rrd.c b/src/libutil/rrd.c
index ec061dd1a..fca4ecad2 100644
--- a/src/libutil/rrd.c
+++ b/src/libutil/rrd.c
@@ -350,6 +350,40 @@ rspamd_rrd_calculate_checksum (struct rspamd_rrd_file *file)
}
}
+static int
+rspamd_rrd_open_exclusive (const gchar *filename)
+{
+ struct timespec sleep_ts = {
+ .tv_sec = 0,
+ .tv_nsec = 1000000
+ };
+ gint fd;
+
+ fd = open (filename, O_RDWR);
+
+ if (fd == -1) {
+ return -1;
+ }
+
+ for (;;) {
+ if (rspamd_file_lock (fd, TRUE) == -1) {
+ if (errno == EAGAIN || errno == EWOULDBLOCK) {
+ nanosleep (&sleep_ts, NULL);
+ continue;
+ }
+ else {
+ close (fd);
+ return -1;
+ }
+ }
+ else {
+ break;
+ }
+ }
+
+ return fd;
+};
+
/**
* Open completed or incompleted rrd file
* @param filename
@@ -376,7 +410,7 @@ rspamd_rrd_open_common (const gchar *filename, gboolean completed, GError **err)
}
/* Open file */
- fd = open (filename, O_RDWR);
+ fd = rspamd_rrd_open_exclusive (filename);
if (fd == -1) {
g_set_error (err,
rrd_error_quark (), errno, "rrd open error: %s", strerror (errno));
@@ -386,14 +420,17 @@ rspamd_rrd_open_common (const gchar *filename, gboolean completed, GError **err)
if (fstat (fd, &st) == -1) {
g_set_error (err,
rrd_error_quark (), errno, "rrd stat error: %s", strerror (errno));
+ rspamd_file_unlock (fd, FALSE);
close (fd);
return FALSE;
}
/* Mmap file */
file->size = st.st_size;
if ((file->map =
- mmap (NULL, st.st_size, PROT_READ | PROT_WRITE, MAP_SHARED, fd,
- 0)) == MAP_FAILED) {
+ mmap (NULL, st.st_size, PROT_READ | PROT_WRITE,
+ MAP_SHARED, fd, 0)) == MAP_FAILED) {
+
+ rspamd_file_unlock (fd, FALSE);
close (fd);
g_set_error (err,
rrd_error_quark (), ENOMEM, "mmap failed: %s", strerror (errno));
@@ -401,7 +438,7 @@ rspamd_rrd_open_common (const gchar *filename, gboolean completed, GError **err)
return NULL;
}
- close (fd);
+ file->fd = fd;
/* Adjust pointers */
rspamd_rrd_adjust_pointers (file, completed);
@@ -462,7 +499,7 @@ rspamd_rrd_create (const gchar *filename,
guint i, j;
/* Open file */
- fd = open (filename, O_RDWR | O_CREAT | O_TRUNC, 0644);
+ fd = open (filename, O_RDWR | O_CREAT | O_EXCL, 0644);
if (fd == -1) {
g_set_error (err,
rrd_error_quark (), errno, "rrd create error: %s",
@@ -470,6 +507,8 @@ rspamd_rrd_create (const gchar *filename,
return NULL;
}
+ rspamd_file_lock (fd, FALSE);
+
/* Fill header */
memset (&head, 0, sizeof (head));
head.rra_cnt = rra_count;
@@ -480,6 +519,7 @@ rspamd_rrd_create (const gchar *filename,
head.float_cookie = RRD_FLOAT_COOKIE;
if (write (fd, &head, sizeof (head)) != sizeof (head)) {
+ rspamd_file_unlock (fd, FALSE);
close (fd);
g_set_error (err,
rrd_error_quark (), errno, "rrd write error: %s", strerror (errno));
@@ -493,6 +533,7 @@ rspamd_rrd_create (const gchar *filename,
memset (&ds.par, 0, sizeof (ds.par));
for (i = 0; i < ds_count; i++) {
if (write (fd, &ds, sizeof (ds)) != sizeof (ds)) {
+ rspamd_file_unlock (fd, FALSE);
close (fd);
g_set_error (err,
rrd_error_quark (), errno, "rrd write error: %s",
@@ -508,6 +549,7 @@ rspamd_rrd_create (const gchar *filename,
memset (&rra.par, 0, sizeof (rra.par));
for (i = 0; i < rra_count; i++) {
if (write (fd, &rra, sizeof (rra)) != sizeof (rra)) {
+ rspamd_file_unlock (fd, FALSE);
close (fd);
g_set_error (err,
rrd_error_quark (), errno, "rrd write error: %s",
@@ -522,6 +564,7 @@ rspamd_rrd_create (const gchar *filename,
lh.last_up_usec = (glong)((initial_ticks - lh.last_up) * 1e6f);
if (write (fd, &lh, sizeof (lh)) != sizeof (lh)) {
+ rspamd_file_unlock (fd, FALSE);
close (fd);
g_set_error (err,
rrd_error_quark (), errno, "rrd write error: %s", strerror (errno));
@@ -537,6 +580,7 @@ rspamd_rrd_create (const gchar *filename,
for (i = 0; i < ds_count; i++) {
if (write (fd, &pdp, sizeof (pdp)) != sizeof (pdp)) {
+ rspamd_file_unlock (fd, FALSE);
close (fd);
g_set_error (err,
rrd_error_quark (), errno, "rrd write error: %s",
@@ -554,6 +598,7 @@ rspamd_rrd_create (const gchar *filename,
for (i = 0; i < rra_count; i++) {
for (j = 0; j < ds_count; j++) {
if (write (fd, &cdp, sizeof (cdp)) != sizeof (cdp)) {
+ rspamd_file_unlock (fd, FALSE);
close (fd);
g_set_error (err,
rrd_error_quark (), errno, "rrd write error: %s",
@@ -567,6 +612,7 @@ rspamd_rrd_create (const gchar *filename,
memset (&rra_ptr, 0, sizeof (rra_ptr));
for (i = 0; i < rra_count; i++) {
if (write (fd, &rra_ptr, sizeof (rra_ptr)) != sizeof (rra_ptr)) {
+ rspamd_file_unlock (fd, FALSE);
close (fd);
g_set_error (err,
rrd_error_quark (), errno, "rrd write error: %s",
@@ -575,7 +621,9 @@ rspamd_rrd_create (const gchar *filename,
}
}
+ rspamd_file_unlock (fd, FALSE);
close (fd);
+
new = rspamd_rrd_open_common (filename, FALSE, err);
return new;
@@ -643,18 +691,13 @@ rspamd_rrd_finalize (struct rspamd_rrd_file *file, GError **err)
gdouble vbuf[1024];
struct stat st;
- if (file == NULL || file->filename == NULL) {
+ if (file == NULL || file->filename == NULL || file->fd == -1) {
g_set_error (err,
rrd_error_quark (), EINVAL, "rrd add rra failed: wrong arguments");
return FALSE;
}
- fd = open (file->filename, O_RDWR);
- if (fd == -1) {
- g_set_error (err,
- rrd_error_quark (), errno, "rrd open error: %s", strerror (errno));
- return FALSE;
- }
+ fd = file->fd;
if (lseek (fd, 0, SEEK_END) == -1) {
g_set_error (err,
@@ -710,7 +753,7 @@ rspamd_rrd_finalize (struct rspamd_rrd_file *file, GError **err)
g_slice_free1 (sizeof (struct rspamd_rrd_file), file);
return FALSE;
}
- close (fd);
+
/* Adjust pointers */
rspamd_rrd_adjust_pointers (file, TRUE);
@@ -1214,6 +1257,7 @@ rspamd_rrd_close (struct rspamd_rrd_file * file)
}
munmap (file->map, file->size);
+ close (file->fd);
g_free (file->filename);
g_free (file->id);
diff --git a/src/libutil/rrd.h b/src/libutil/rrd.h
index c7bc8008a..d24249965 100644
--- a/src/libutil/rrd.h
+++ b/src/libutil/rrd.h
@@ -204,6 +204,7 @@ struct rspamd_rrd_file {
gsize size; /* its size */
gboolean finalized;
gchar *id;
+ gint fd;
};