summaryrefslogtreecommitdiff
path: root/src/journal/journal-send.c
diff options
context:
space:
mode:
authorLennart Poettering <lennart@poettering.net>2012-01-14 01:53:20 +0100
committerLennart Poettering <lennart@poettering.net>2012-01-14 01:54:33 +0100
commit0dad12c190b7493955cd60d2a1625199b1709f69 (patch)
tree607e747209911ae62a71a23bbc5cb71a6e492580 /src/journal/journal-send.c
parentf5e04665ebf7124f3ea17dcf258793ed73a95fe1 (diff)
journal: if the data to be sent is larger than the maximum datagram size resort to passing a temporary fd over native protocol
Diffstat (limited to 'src/journal/journal-send.c')
-rw-r--r--src/journal/journal-send.c57
1 files changed, 55 insertions, 2 deletions
diff --git a/src/journal/journal-send.c b/src/journal/journal-send.c
index d51aec9690..03bd170728 100644
--- a/src/journal/journal-send.c
+++ b/src/journal/journal-send.c
@@ -23,6 +23,8 @@
#include <sys/un.h>
#include <errno.h>
#include <stddef.h>
+#include <unistd.h>
+#include <fcntl.h>
#include "sd-journal.h"
#include "util.h"
@@ -132,12 +134,19 @@ fail:
}
_public_ int sd_journal_sendv(const struct iovec *iov, int n) {
- int fd;
+ int fd, buffer_fd;
struct iovec *w;
uint64_t *l;
int i, j = 0;
struct msghdr mh;
struct sockaddr_un sa;
+ char path[] = "/tmp/journal.XXXXXX";
+ ssize_t k;
+ union {
+ struct cmsghdr cmsghdr;
+ uint8_t buf[CMSG_SPACE(sizeof(int))];
+ } control;
+ struct cmsghdr *cmsg;
if (!iov || n <= 0)
return -EINVAL;
@@ -203,7 +212,51 @@ _public_ int sd_journal_sendv(const struct iovec *iov, int n) {
mh.msg_iov = w;
mh.msg_iovlen = j;
- if (sendmsg(fd, &mh, MSG_NOSIGNAL) < 0)
+ k = sendmsg(fd, &mh, MSG_NOSIGNAL);
+ if (k >= 0)
+ return 0;
+
+ if (errno != EMSGSIZE)
+ return -errno;
+
+ /* Message doesn't fit... Let's dump the data in a temporary
+ * file and just pass a file descriptor of it to the other
+ * side */
+
+ buffer_fd = mkostemp(path, O_CLOEXEC|O_RDWR);
+ if (buffer_fd < 0)
+ return -errno;
+
+ if (unlink(path) < 0) {
+ close_nointr_nofail(buffer_fd);
+ return -errno;
+ }
+
+ n = writev(buffer_fd, w, j);
+ if (n < 0) {
+ close_nointr_nofail(buffer_fd);
+ return -errno;
+ }
+
+ mh.msg_iov = NULL;
+ mh.msg_iovlen = 0;
+
+ zero(control);
+ mh.msg_control = &control;
+ mh.msg_controllen = sizeof(control);
+
+ cmsg = CMSG_FIRSTHDR(&mh);
+ cmsg->cmsg_level = SOL_SOCKET;
+ cmsg->cmsg_type = SCM_RIGHTS;
+ cmsg->cmsg_len = CMSG_LEN(sizeof(int));
+ memcpy(CMSG_DATA(cmsg), &buffer_fd, sizeof(int));
+
+ mh.msg_controllen = cmsg->cmsg_len;
+
+ k = sendmsg(fd, &mh, MSG_NOSIGNAL);
+ close_nointr_nofail(buffer_fd);
+
+ if (k < 0)
return -errno;
return 0;