Move runas.h to common/ directory
[lttng-tools.git] / liblttng-kconsumer / lttng-kconsumer.c
index 778dd1631520d61c6c8eab2ae7a525d8c9a5660e..2b69438cadb2b1e7d469ecd5c9f671b5aa36e670 100644 (file)
@@ -34,6 +34,8 @@
 #include <lttng/lttng-kconsumer.h>
 #include <lttngerr.h>
 
+#include "common/runas.h"
+
 extern struct lttng_consumer_global_data consumer_data;
 extern int consumer_poll_timeout;
 extern volatile int consumer_quit;
@@ -256,7 +258,9 @@ int lttng_kconsumer_recv_cmd(struct lttng_consumer_local_data *ctx,
                                msg.u.stream.state,
                                msg.u.stream.mmap_len,
                                msg.u.stream.output,
-                               msg.u.stream.path_name);
+                               msg.u.stream.path_name,
+                               msg.u.stream.uid,
+                               msg.u.stream.gid);
                if (new_stream == NULL) {
                        lttng_consumer_send_error(ctx, CONSUMERD_OUTFD_ERROR);
                        goto end;
@@ -300,3 +304,143 @@ end:
 end_nosignal:
        return 0;
 }
+
+/*
+ * Consume data on a file descriptor and write it on a trace file.
+ */
+int lttng_kconsumer_read_subbuffer(struct lttng_consumer_stream *stream,
+               struct lttng_consumer_local_data *ctx)
+{
+       unsigned long len;
+       int err;
+       long ret = 0;
+       int infd = stream->wait_fd;
+
+       DBG("In read_subbuffer (infd : %d)", infd);
+       /* Get the next subbuffer */
+       err = kernctl_get_next_subbuf(infd);
+       if (err != 0) {
+               ret = errno;
+               /*
+                * This is a debug message even for single-threaded consumer,
+                * because poll() have more relaxed criterions than get subbuf,
+                * so get_subbuf may fail for short race windows where poll()
+                * would issue wakeups.
+                */
+               DBG("Reserving sub buffer failed (everything is normal, "
+                               "it is due to concurrency)");
+               goto end;
+       }
+
+       switch (stream->output) {
+               case LTTNG_EVENT_SPLICE:
+                       /* read the whole subbuffer */
+                       err = kernctl_get_padded_subbuf_size(infd, &len);
+                       if (err != 0) {
+                               ret = errno;
+                               perror("Getting sub-buffer len failed.");
+                               goto end;
+                       }
+
+                       /* splice the subbuffer to the tracefile */
+                       ret = lttng_consumer_on_read_subbuffer_splice(ctx, stream, len);
+                       if (ret < 0) {
+                               /*
+                                * display the error but continue processing to try
+                                * to release the subbuffer
+                                */
+                               ERR("Error splicing to tracefile");
+                       }
+                       break;
+               case LTTNG_EVENT_MMAP:
+                       /* read the used subbuffer size */
+                       err = kernctl_get_padded_subbuf_size(infd, &len);
+                       if (err != 0) {
+                               ret = errno;
+                               perror("Getting sub-buffer len failed.");
+                               goto end;
+                       }
+                       /* write the subbuffer to the tracefile */
+                       ret = lttng_consumer_on_read_subbuffer_mmap(ctx, stream, len);
+                       if (ret < 0) {
+                               /*
+                                * display the error but continue processing to try
+                                * to release the subbuffer
+                                */
+                               ERR("Error writing to tracefile");
+                       }
+                       break;
+               default:
+                       ERR("Unknown output method");
+                       ret = -1;
+       }
+
+       err = kernctl_put_next_subbuf(infd);
+       if (err != 0) {
+               ret = errno;
+               if (errno == EFAULT) {
+                       perror("Error in unreserving sub buffer\n");
+               } else if (errno == EIO) {
+                       /* Should never happen with newer LTTng versions */
+                       perror("Reader has been pushed by the writer, last sub-buffer corrupted.");
+               }
+               goto end;
+       }
+
+end:
+       return ret;
+}
+
+int lttng_kconsumer_on_recv_stream(struct lttng_consumer_stream *stream)
+{
+       int ret;
+
+       /* Opening the tracefile in write mode */
+       if (stream->path_name != NULL) {
+               ret = open_run_as(stream->path_name,
+                               O_WRONLY|O_CREAT|O_TRUNC,
+                               S_IRWXU|S_IRWXG|S_IRWXO,
+                               stream->uid, stream->gid);
+               if (ret < 0) {
+                       ERR("Opening %s", stream->path_name);
+                       perror("open");
+                       goto error;
+               }
+               stream->out_fd = ret;
+       }
+
+       if (stream->output == LTTNG_EVENT_MMAP) {
+               /* get the len of the mmap region */
+               unsigned long mmap_len;
+
+               ret = kernctl_get_mmap_len(stream->wait_fd, &mmap_len);
+               if (ret != 0) {
+                       ret = errno;
+                       perror("kernctl_get_mmap_len");
+                       goto error_close_fd;
+               }
+               stream->mmap_len = (size_t) mmap_len;
+
+               stream->mmap_base = mmap(NULL, stream->mmap_len,
+                               PROT_READ, MAP_PRIVATE, stream->wait_fd, 0);
+               if (stream->mmap_base == MAP_FAILED) {
+                       perror("Error mmaping");
+                       ret = -1;
+                       goto error_close_fd;
+               }
+       }
+
+       /* we return 0 to let the library handle the FD internally */
+       return 0;
+
+error_close_fd:
+       {
+               int err;
+
+               err = close(stream->out_fd);
+               assert(!err);
+       }
+error:
+       return ret;
+}
+
This page took 0.024359 seconds and 4 git commands to generate.