diff options
Diffstat (limited to 'src/libutil')
-rw-r--r-- | src/libutil/rrd.c | 70 | ||||
-rw-r--r-- | src/libutil/rrd.h | 1 |
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; }; |