util: add buffer ops 61/166561/23
authorMichal Bloch <m.bloch@samsung.com>
Thu, 8 Feb 2018 13:12:09 +0000 (14:12 +0100)
committerMichal Bloch <m.bloch@samsung.com>
Tue, 20 Feb 2018 15:53:42 +0000 (16:53 +0100)
Change-Id: Id0fee76de71e46565afde89afaf906d3f11a34b7
Signed-off-by: Michal Bloch <m.bloch@samsung.com>
src/logutil/fd_info.c
src/logutil/fd_info.h
src/logutil/fdi_binfile.c
src/logutil/fdi_binfile.h
src/logutil/fdi_logger.c
src/logutil/fdi_logger.h
src/logutil/fdi_pipe.c
src/logutil/fdi_pipe.h
src/logutil/logutil.c

index 379a65e..464aa77 100644 (file)
 /**
  * @brief Create struct fd_info
  * @details Allocates memory for the struct and initializes it with given arguments
- * @param[in] fd file descriptor
- * @param[in] do_sorting specifies if the logs read from fd should be sorted
- * @param[in] log_len up to how many bytes the logs should be read from fd
- *                    UNLIMITED_LOG_LEN for unlimited logs reading
- * @param[in] type source type we read from defined in enum fd_type
+ * @param[in] ops source-dependent operation set
  * @return FD created struct or NULL on memory allocation failure
  */
-struct fd_info *fdi_create(int fd, int do_sorting, int log_len, fd_type type)
+struct fd_info *fdi_create(struct fd_ops *ops, const char *name)
 {
+       assert(ops);
+
        struct fd_info *fdi = malloc(sizeof(struct fd_info));
        if (!fdi)
                return NULL;
 
-       fdi->fd = fd;
-       fdi->do_sorting = do_sorting;
-       fdi->log_len = log_len;
-       fdi->type = type;
-       fdi->index = 0;
+       fdi->fd = -1;
+       fdi->log_len = UNLIMITED_LOG_LEN;
+       fdi->ops = ops;
+       fdi->name = name;
+       fdi->priv_data = NULL;
 
        return fdi;
 }
@@ -40,8 +38,12 @@ void fdi_free(struct fd_info *fdi)
        if (!fdi)
                return;
 
+       if (fdi->ops->destroy)
+               fdi->ops->destroy(fdi);
+
        if (fdi->fd >= 0)
                close(fdi->fd);
+
        free(fdi);
 }
 
@@ -58,40 +60,37 @@ void fdi_array_free(struct fd_info ***arr)
        free(*arr);
 }
 
-bool fdi_has_log(struct fd_info *fdi)
+bool generic_has_log(struct fd_info *fdi)
 {
        assert(fdi);
-       const struct logger_entry *const le = (const struct logger_entry *)fdi->buff;
-       return fdi->index >= sizeof le->len && fdi->index >= le->len;
+       struct generic_priv_data *gpd = (struct generic_priv_data *)fdi->priv_data;
+       assert(gpd);
+
+       const struct logger_entry *const le = (const struct logger_entry *)gpd->buff;
+       return gpd->index >= sizeof le->len && gpd->index >= le->len;
 }
 
-int fdi_push_log(struct fd_info *fdi, int *dump, struct sort_vector *logs, struct log_file *l_file)
+int fdi_push_log(struct fd_info *fdi, struct sort_vector *logs, struct log_file *l_file)
 {
        assert(fdi);
-       assert(dump);
        assert(l_file);
 
-       struct logger_entry *temp = fdi_extract_entry(fdi);
+       struct logger_entry *temp = fdi->ops->extract_entry(fdi);
        if (!temp)
                return -ENOMEM;
 
-       if (fdi->do_sorting) {
-               sort_vector_push(logs, temp, l_file);
-       } else {
-               int write_err = logfile_write_with_rotation(temp, l_file);
-               free(temp);
-               if (!write_err && *dump && !--*dump)
-                       return 1;
-       }
+       sort_vector_push(logs, temp, l_file);
 
        return 0;
 }
 
-struct logger_entry *fdi_extract_entry(struct fd_info *fdi)
+struct logger_entry *generic_extract_entry(struct fd_info *fdi)
 {
        assert(fdi);
+       struct generic_priv_data *gpd = (struct generic_priv_data *)fdi->priv_data;
+       assert(gpd);
 
-       struct logger_entry *const buf_le = (struct logger_entry *)fdi->buff;
+       struct logger_entry *const buf_le = (struct logger_entry *)gpd->buff;
        if (!buf_le->len)
                return NULL;
 
@@ -100,35 +99,26 @@ struct logger_entry *fdi_extract_entry(struct fd_info *fdi)
                return NULL;
 
        memcpy(new_le, buf_le, buf_le->len);
-       fdi->index -= buf_le->len;
-       memmove(fdi->buff, fdi->buff + buf_le->len, fdi->index);
+       gpd->index -= buf_le->len;
+       memmove(gpd->buff, gpd->buff + buf_le->len, gpd->index);
 
        return new_le;
 }
 
-int fdi_read(struct fd_info *fdi)
+int generic_read(struct fd_info *fdi)
 {
        assert(fdi);
+       struct generic_priv_data *gpd = (struct generic_priv_data *)fdi->priv_data;
+       assert(gpd);
 
-       if (fdi->index == RECEIVE_BUFFER_SIZE)
+       if (gpd->index == RECEIVE_BUFFER_SIZE)
                return -EAGAIN;
 
-       int r = read(fdi->fd, fdi->buff + fdi->index, RECEIVE_BUFFER_SIZE - fdi->index);
+       int r = read(fdi->fd, gpd->buff + gpd->index, RECEIVE_BUFFER_SIZE - gpd->index);
        if (r < 0)
                return -errno;
 
-       if (fdi->type == ANDROID_LOGGER) {
-               struct logger_entry *const le = (struct logger_entry *)fdi->buff;
-               parse_androidlogger_message((struct android_logger_entry *)fdi->buff, le, r);
-               add_recv_timestamp(le);
-               fdi->index = le->len;
-       } else {
-               fdi->index += r;
-       }
-
-       if (fdi->log_len > 0)
-               fdi->log_len -= r;
-
+       gpd->index += r;
        return r;
 }
 
index 3f450ec..5f42288 100644 (file)
@@ -1,33 +1,63 @@
 #pragma once
 
 #include <stdbool.h>
+#include <logconfig.h>
 #include <log_file.h>
+#include <logprint.h>
+#include <ptrs_list.h>
 #include <queued_entry.h>
 #include "sort_vector.h"
 
-#define RECEIVE_BUFFER_SIZE 16384 // How large (in bytes) the pipe receiving buffer is.
+#define RECEIVE_BUFFER_SIZE 16384 // How large (in bytes) pipe receiving buffer is.
 #define UNLIMITED_LOG_LEN (-RECEIVE_BUFFER_SIZE - 1) // value not reachable through a single read()
 
-typedef enum {
-       PIPE,
-       BINARY_FILE,
-       ANDROID_LOGGER
-} fd_type;
+struct fd_ops;
 
 struct fd_info {
        int fd;
-       int do_sorting;
        int log_len;
-       fd_type type;
-       int index;
-       char buff[RECEIVE_BUFFER_SIZE];
+       struct fd_ops *ops;
+       const char *name;
+       void *priv_data;
+};
+
+
+struct fd_ops {
+       /// Lifetime management: constructor and destructor
+       int (*create)(struct fd_info *fdi, struct log_config *conf, const char *name);
+       void (*destroy)(struct fd_info *fdi);
+
+       /// Read an entry into an internal buffer; requires `prepare_print` to have been called
+       int (*read)(struct fd_info *fdi);
+
+       /// Checks whether a log has been buffered and is ready for extraction
+       bool (*has_log)(struct fd_info *fdi);
+
+       /// Extracts a buffered entry and relinquishes its ownership
+       struct logger_entry *(*extract_entry)(struct fd_info *fdi);
+
+       /// Transition into a state that allows reading and printing out logs
+       int (*prepare_print)(struct fd_info *fdi, int dump, list_head filters, log_format *format);
+
+       /// Clear the buffer
+       int (*clear)(struct fd_info *fdi);
 };
 
-struct fd_info *fdi_create(int fd, int do_sorting, int log_len, fd_type type);
+struct fd_info *fdi_create(struct fd_ops *ops, const char *name);
 void fdi_free(struct fd_info *fdi);
 void fdi_array_free(struct fd_info ***arr);
 bool fdi_has_log(struct fd_info *fdi);
-int fdi_push_log(struct fd_info *fdi, int *dump, struct sort_vector *logs, struct log_file *l_file);
+int fdi_push_log(struct fd_info *fdi, struct sort_vector *logs, struct log_file *l_file);
 struct logger_entry *fdi_extract_entry(struct fd_info *fdi);
 int fdi_read(struct fd_info *fdi);
 
+
+struct generic_priv_data {
+       size_t index;
+       char buff[RECEIVE_BUFFER_SIZE];
+};
+
+int generic_read(struct fd_info *fdi);
+struct logger_entry *generic_extract_entry(struct fd_info *fdi);
+bool generic_has_log(struct fd_info *fdi);
+
index 473972f..db04e3f 100644 (file)
 
 /**
  * @brief Handle a file
- * @details Checks validity of a binary file
- * @param[in] filename The file name
- * @return A fd wrapper struct on valid file, else NULL
+ * @details Opens and checks validity of a binary file
+ * @param[in] fdi The fd info to work with
+ * @param[in] conf The configuration to use
+ * @return 0 on success, -errno on failure
  */
-struct fd_info *handle_file(char const *filename)
+static int binaryfile_create(struct fd_info *fdi, struct log_config *conf, const char *name)
 {
-       assert(filename);
+       assert(fdi);
+       assert(conf);
+       assert(name);
 
-       int r;
-       int fd;
-
-       fd = open(filename, O_RDONLY);
+       int fd = open(name, O_RDONLY);
        if (fd < 0) {
-               fprintf(stderr, "File \"%s\" could not be opened: %m\n", filename);
-               return NULL;
+               fprintf(stderr, "File \"%s\" could not be opened: %m\n", name);
+               return -errno;
        }
 
        struct dlog_pipe_header header;
-       r = read(fd, &header, sizeof header);
+       int r = read(fd, &header, sizeof header);
        if (r < 0) {
-               fprintf(stderr, "File \"%s\" read failed! %m\n", filename);
+               r = -errno;
+               fprintf(stderr, "File \"%s\" read failed! %m\n", name);
                goto closefile;
        } else if (r < sizeof header) {
-               fprintf(stderr, "File \"%s\" does not contain a full header!\n", filename);
+               fprintf(stderr, "File \"%s\" does not contain a full header!\n", name);
+               r = -EINVAL;
                goto closefile;
        }
 
        if (header.endian != PIPE_FILE_ENDIAN_MAGIC) {
-               fprintf(stderr, "File \"%s\": unsupported endianness!\n", filename);
+               fprintf(stderr, "File \"%s\": unsupported endianness!\n", name);
+               r = -EINVAL;
                goto closefile;
        }
 
        if (header.version != PIPE_FILE_FORMAT_VERSION) {
-               fprintf(stderr, "File \"%s\": file format version is %d but only %d is supported!\n", filename, header.version, PIPE_FILE_FORMAT_VERSION);
+               fprintf(stderr, "File \"%s\": file format version is %d but only %d is supported!\n", name, header.version, PIPE_FILE_FORMAT_VERSION);
+               r = -EINVAL;
                goto closefile;
        }
 
-       struct fd_info *fdi = fdi_create(fd, 1, UNLIMITED_LOG_LEN, BINARY_FILE);
-       if (!fdi) {
-               fprintf(stderr, "Error: not enough memory\n");
+       struct generic_priv_data *gpd = malloc(sizeof(struct generic_priv_data));
+       if (!gpd) {
+               fprintf(stderr, "Error not enough memory\n");
+               r = -ENOMEM;
                goto closefile;
        }
-       return fdi;
+       gpd->index = 0;
+       fdi->priv_data = gpd;
+
+       fdi->fd = fd;
+       return 0;
 
 closefile:
        close(fd);
-       return NULL;
+       return r;
+}
+
+static void binaryfile_destroy(struct fd_info *fdi)
+{
+       assert(fdi);
+
+       if (!fdi->priv_data)
+               return;
+
+       free(fdi->priv_data);
+       fdi->priv_data = NULL;
 }
 
+static int binaryfile_prepare_print(struct fd_info *fdi, int dump, list_head filters, log_format *format)
+{
+       assert(fdi);
+       assert(filters);
+       assert(format);
+
+       for (list_head iter = filters; iter; list_next(&iter))
+               log_add_filter_string(format, (const char *)list_at(iter));
+
+       return 0;
+}
+
+struct fd_ops ops_binfile = {
+       .create = binaryfile_create,
+       .destroy = binaryfile_destroy,
+       .read = generic_read,
+       .has_log = generic_has_log,
+       .extract_entry = generic_extract_entry,
+       .prepare_print = binaryfile_prepare_print,
+};
+
index 2b9179e..253e216 100644 (file)
@@ -2,5 +2,5 @@
 
 #include "fd_info.h"
 
-struct fd_info *handle_file(char const *filename);
+extern struct fd_ops ops_binfile;
 
index f840057..ed0cd8c 100644 (file)
 #include "fd_info.h"
 #include "fdi_logger.h"
 
+struct logger_priv_data {
+       struct logger_entry *entry;
+};
+
 /**
  * @brief Get buffer filled size
  * @details Sends a get log len ioctl to given fd
@@ -31,58 +35,144 @@ static int logger_get_log_len(int fd)
 /**
  * @brief Clear the buffer
  * @details Sends a clear ioctl to given fd
- * @param[in] fd File descriptor of the buffer
- * @remarks ANDROID LOGGER version
+ * @param[in] fdi File descriptor info
+ * @return 0 on success, -errno on failure
  */
-static void clear_log_logger(int fd)
+static int logger_clear(struct fd_info *fdi)
 {
-       int ret = ioctl(fd, LOGGER_FLUSH_LOG);
-       if (ret < 0)
+       assert(fdi);
+       assert(fdi->fd >= 0);
+
+       int ret = ioctl(fdi->fd, LOGGER_FLUSH_LOG);
+       if (ret < 0) {
                _E("ioctl LOGGER_FLUSH_LOG failed (%d)", errno);
+               return -errno;
+       }
+
+       return 0;
 }
 
 /**
- * @brief Process buffer (non-pipe version)
- * @details Finalizes a buffer: sends the appropriate socket request
- * @param[in] buffer_name The name of the buffer
- * @param[in] clear Whether to clear the buffer
+ * @brief Open an Android Logger device
+ * @param[in] fdi File descriptor info
  * @param[in] conf The configuration
- * @param[in] dump Whether dumping or not
- * @param[in] filters List of filters
- * @param[in] format Log processing format
- * @return FD wrapper structure to read from
+ * @return 0 on success, -errno on failure
  */
-struct fd_info *process_buffer_nonpipe(const char *buffer_name, int clear, struct log_config *conf, list_head filters, log_format *format)
+static int logger_create(struct fd_info *fdi, struct log_config *conf, const char *name)
 {
-       for (list_head iter = filters; iter; list_next(&iter))
-               log_add_filter_string(format, (const char *)list_at(iter));
+       assert(fdi);
+       assert(conf);
+       assert(name);
 
        char const *dev_path;
-       dev_path = log_config_get(conf, buffer_name);
+       dev_path = log_config_get(conf, name);
        if (!dev_path)
-               return NULL;
+               return -ENOENT;
 
-       int fd = open(dev_path, clear ? O_WRONLY : O_RDONLY);
-       if (fd < 0)
-               return NULL;
+       struct logger_priv_data *lpd = malloc(sizeof *lpd);
+       if (!lpd)
+               return -ENOMEM;
+       lpd->entry = NULL;
 
-       if (clear) {
-               clear_log_logger(fd);
-               goto cleanup;
+       int fd = open(dev_path, O_RDWR);
+       if (fd < 0) {
+               free(lpd);
+               return -errno;
        }
 
-       const int log_len = logger_get_log_len(fd);
+       fdi->priv_data = lpd;
+       fdi->fd = fd;
+       return 0;
+}
+
+static void logger_destroy(struct fd_info *fdi)
+{
+       assert(fdi);
+       struct logger_priv_data *lpd = (struct logger_priv_data *)fdi->priv_data;
+
+       if (!lpd)
+               return;
+
+       free(lpd->entry);
+       free(lpd);
+       fdi->priv_data = NULL;
+}
+
+static int logger_prepare_print(struct fd_info *fdi, int dump, list_head filters, log_format *format)
+{
+       assert(fdi);
+       assert(format);
+
+       for (list_head iter = filters; iter; list_next(&iter))
+               log_add_filter_string(format, (const char *)list_at(iter));
+
+       if (!dump)
+               return 0;
+
+       const int log_len = logger_get_log_len(fdi->fd);
        if (log_len < 0)
-               goto cleanup;
+               return log_len;
+
+       fdi->log_len = log_len;
+       return 0;
+}
+
+static int logger_read(struct fd_info *fdi)
+{
+       assert(fdi);
+       struct logger_priv_data *lpd = (struct logger_priv_data *)fdi->priv_data;
+       assert(lpd);
+       assert(!lpd->entry);
+
+       char buff[LOG_MAX_SIZE];
+       int r = read(fdi->fd, buff, sizeof buff);
+       if (r < 0)
+               return -errno;
+
+       struct android_logger_entry *const ale = (struct android_logger_entry *)buff;
+       if (r <= sizeof *ale)
+               return -EINVAL;
 
-       struct fd_info *fdi = fdi_create(fd, 1, log_len, ANDROID_LOGGER);
-       if (!fdi)
-               goto cleanup;
+       lpd->entry = malloc(r - sizeof *ale + sizeof *lpd->entry);
+       if (!lpd->entry)
+               return -ENOMEM;
 
-       return fdi;
+       parse_androidlogger_message(ale, lpd->entry, r);
+       add_recv_timestamp(lpd->entry);
 
-cleanup:
-       close(fd);
-       return NULL;
+       if (fdi->log_len > 0)
+               fdi->log_len -= r;
+
+       return r;
 }
 
+static struct logger_entry *logger_extract_entry(struct fd_info *fdi)
+{
+       assert(fdi);
+       struct logger_priv_data *lpd = (struct logger_priv_data *)fdi->priv_data;
+       assert(lpd);
+
+       struct logger_entry *const ret = lpd->entry;
+       lpd->entry = NULL;
+       return ret;
+}
+
+static bool logger_has_log(struct fd_info *fdi)
+{
+       assert(fdi);
+       struct logger_priv_data *lpd = (struct logger_priv_data *)fdi->priv_data;
+       assert(lpd);
+
+       return lpd->entry != NULL;
+}
+
+struct fd_ops ops_logger = {
+       .create = logger_create,
+       .destroy = logger_destroy,
+       .read = logger_read,
+       .has_log = logger_has_log,
+       .extract_entry = logger_extract_entry,
+       .prepare_print = logger_prepare_print,
+       .clear = logger_clear,
+};
+
index af80cd3..ec6627c 100644 (file)
@@ -1,9 +1,6 @@
 #pragma once
 
-#include <logconfig.h>
-#include <logprint.h>
-#include <ptrs_list.h>
 #include "fd_info.h"
 
-struct fd_info *process_buffer_nonpipe(const char *buffer_name, int clear, struct log_config *conf, list_head filters, log_format *format);
+extern struct fd_ops ops_logger;
 
index b7e709e..371295b 100644 (file)
@@ -9,17 +9,25 @@
 #include "fd_info.h"
 #include "fdi_pipe.h"
 
+struct pipe_priv_data {
+       struct generic_priv_data gpd; // "base class", has to be first
+       int sock_fd;
+};
+
 /**
  * @brief Clear request
  * @details Send a CLEAR request to the logger daemon
- * @param[in] sock_fd The socket to send the request over
- * @return 1 on success, 0 on failure
+ * @param[in] fdi The fd info to work on
+ * @return 0 on success, -errno on failure
  */
-static int do_clear_pipe(int sock_fd)
+static int pipe_clear(struct fd_info *fdi)
 {
-       assert(sock_fd >= 0);
+       assert(fdi);
+       struct pipe_priv_data *ppd = (struct pipe_priv_data *)fdi->priv_data;
+       assert(ppd);
+       assert(ppd->sock_fd >= 0);
 
-       int r = send_dlog_request(sock_fd, DLOG_REQ_CLEAR, NULL, 0);
+       int r = send_dlog_request(ppd->sock_fd, DLOG_REQ_CLEAR, NULL, 0);
        if (r < 0)
                printf("Error: could not send a CLEAR request to logger %s\n", strerror(-r));
 
@@ -66,69 +74,92 @@ static int send_logger_request(list_head filters, int dump, int sock_fd)
 
        return r;
 }
+
 /**
- * @brief Process buffer (pipe version)
- * @details Finalizes a buffer: sends the appropriate socket request
- * @param[in] buffer_name The name of the buffer
- * @param[in] clear Whether to clear the buffer
+ * @brief Open a connection to the dlog daemon
+ * @param[in] fdi File descriptor info
  * @param[in] conf The configuration
- * @param[in] dump Whether dumping or not
- * @param[in] filters List of filters
- * @param[in] format Log processing format
- * @return FD wrapper structure of a pipe if we are to read from one, else NULL
+ * @return 0 on success, -errno on failure
  */
-
-struct fd_info *process_buffer_pipe(const char *buffer_name, int clear, struct log_config *conf, int dump, list_head filters, log_format *format)
+static int pipe_create(struct fd_info *fdi, struct log_config *conf, const char *name)
 {
-       char conf_key[MAX_CONF_KEY_LEN];
-       char const * sock_path;
-       int sock_fd = -1;
-       int pipe_fd;
-       struct fd_info *ret = NULL;
+       assert(fdi);
+       assert(conf);
+       assert(name);
 
-       log_add_filter_string(format, "*:V"); // use the widest possible filter to let everything through as data are already filtered daemonside
+       char conf_key[MAX_CONF_KEY_LEN];
+       snprintf(conf_key, sizeof(conf_key), "%s_ctl_sock", name);
 
-       snprintf(conf_key, sizeof(conf_key), "%s_ctl_sock", buffer_name);
-       sock_path = log_config_get(conf, conf_key);
+       const char *sock_path = log_config_get(conf, conf_key);
        if (!sock_path) {
-               printf("Error: Socket %s is unavailable!\n", conf_key);
-               goto cleanup;
+               printf("Error: no config entry for  %s!\n", conf_key);
+               return -ENOENT;
        }
 
-       sock_fd = connect_sock(sock_path);
+       int sock_fd = connect_sock(sock_path);
        if (sock_fd < 0) {
-               printf("Error: Could not connect to socket %s!\n", sock_path);
-               goto cleanup;
+               printf("Error: Could not connect to socket %s %s!\n", sock_path, strerror(-sock_fd));
+               return sock_fd;
        }
 
-       if (clear) {
-               do_clear_pipe(sock_fd);
-               goto cleanup;
+       struct pipe_priv_data *ppd = malloc(sizeof *ppd);
+       if (!ppd) {
+               printf("Error: not enough memory\n");
+               close(sock_fd);
+               return -ENOMEM;
        }
+       ppd->gpd.index = 0;
+       ppd->sock_fd = sock_fd;
 
-       if (send_logger_request(filters, dump, sock_fd) < 0) {
-               printf("Error: could not send request to logger daemon\n");
-               goto cleanup;
-       }
+       fdi->priv_data = ppd;
+       return 0;
+}
 
-       pipe_fd = recv_pipe(sock_fd);
-       if (pipe_fd < 0) {
-               printf("Error: couldn't retrieve pipe fd\n");
-               goto cleanup;
-       }
+static void pipe_destroy(struct fd_info *fdi)
+{
+       assert(fdi);
+       struct pipe_priv_data *ppd = (struct pipe_priv_data *)fdi->priv_data;
+       if (!ppd)
+               return;
 
-       int do_sorting = strcmp(buffer_name, "kmsg") && strcmp(buffer_name, "syslog");
-       ret = fdi_create(pipe_fd, do_sorting, UNLIMITED_LOG_LEN, PIPE);
+       if (ppd->sock_fd >= 0)
+               close(ppd->sock_fd);
+       free(ppd);
 
-       if (!ret) {
-               close(pipe_fd);
-               goto cleanup;
-       }
+       fdi->priv_data = NULL;
+}
 
-cleanup:
-       if (sock_fd >= 0)
-               close(sock_fd);
+static int pipe_prepare_print(struct fd_info *fdi, int dump, list_head filters, log_format *format)
+{
+       assert(filters);
+       assert(format);
+       assert(fdi);
+       struct pipe_priv_data *ppd = (struct pipe_priv_data *)fdi->priv_data;
+       assert(ppd);
+       assert(ppd->sock_fd >= 0);
 
-       return ret;
+       log_add_filter_string(format, "*:V"); // lets everything through (actual filtering done by the daemon)
+
+       int r = send_logger_request(filters, dump, ppd->sock_fd);
+       if (r < 0)
+               return r;
+
+       int pipe_fd = recv_pipe(ppd->sock_fd);
+       if (pipe_fd < 0)
+               return pipe_fd;
+
+       fdi->fd = pipe_fd;
+
+       return 0;
 }
 
+struct fd_ops ops_pipe = {
+       .create = pipe_create,
+       .destroy = pipe_destroy,
+       .read = generic_read,
+       .has_log = generic_has_log,
+       .extract_entry = generic_extract_entry,
+       .prepare_print = pipe_prepare_print,
+       .clear = pipe_clear,
+};
+
index d6896e6..d510636 100644 (file)
@@ -1,9 +1,6 @@
 #pragma once
 
-#include <logconfig.h>
-#include <logprint.h>
-#include <ptrs_list.h>
 #include "fd_info.h"
 
-struct fd_info *process_buffer_pipe(const char *buffer_name, int clear, struct log_config *conf, int dump, list_head filters, log_format *format);
+extern struct fd_ops ops_pipe;
 
index d17696f..ef006e7 100755 (executable)
@@ -119,7 +119,7 @@ static int process_log(struct logger_entry *e, struct logger_entry *last, struct
  * @param[in] logs The log sorting vector
  * @param[in] l_file File output metadata
  */
-static void handle_pipe(struct fd_info **data_fds, int fd_count, int dump, struct sort_vector *logs, struct log_file *l_file)
+static void do_print(struct fd_info **data_fds, int fd_count, int dump, struct sort_vector *logs, struct log_file *l_file)
 {
        assert(data_fds);
        assert(logs);
@@ -146,9 +146,9 @@ static void handle_pipe(struct fd_info **data_fds, int fd_count, int dump, struc
                ev.data.ptr = data_fds[nfds];
                if (fd_set_flags(fd, O_NONBLOCK) < 0)
                        return;
-               if (data_fds[nfds]->type == PIPE)
+               if (data_fds[nfds]->ops == &ops_pipe) // HACK
                        ++pipes;
-               if (data_fds[nfds]->type != BINARY_FILE) {
+               if (data_fds[nfds]->ops != &ops_binfile) { // HACK
                        epoll_ctl(epollfd, EPOLL_CTL_ADD, fd, &ev);
                        struct fd_info *swap_tmp = data_fds[nfds];
                        data_fds[nfds--] = data_fds[--fd_count];
@@ -207,7 +207,7 @@ static void handle_pipe(struct fd_info **data_fds, int fd_count, int dump, struc
                        continue;
                }
 
-               r = fdi_read(fdi);
+               r = fdi->ops->read(fdi);
                if (r < 0) {
                        if (r == -EAGAIN)
                                continue;
@@ -216,10 +216,10 @@ static void handle_pipe(struct fd_info **data_fds, int fd_count, int dump, struc
                }
 
                if (r == 0 || (dump && fdi->log_len <= 0 && fdi->log_len != UNLIMITED_LOG_LEN)) {
-                       if (fdi->type != BINARY_FILE)
+                       if (fdi->ops != &ops_binfile) // HACK
                                epoll_ctl(epollfd, EPOLL_CTL_DEL, fdi->fd, NULL);
 
-                       if (fdi->type == PIPE && dump)
+                       if (fdi->ops == &ops_pipe && dump) // HACK
                                --pipes;
                        else if (--fd_count <= 0) {
                                accepting_logs = 0;
@@ -227,8 +227,8 @@ static void handle_pipe(struct fd_info **data_fds, int fd_count, int dump, struc
                        }
                }
 
-               while (fdi_has_log(fdi))
-                       if (fdi_push_log(fdi, &dump, logs, l_file)) {
+               while (fdi->ops->has_log(fdi))
+                       if (fdi_push_log(fdi, logs, l_file)) {
                                looping = 0;
                                break;
                        }
@@ -351,6 +351,74 @@ static int validate_buffer_set(int *enabled_buffers, int files_cnt)
        return 1;
 }
 
+int create_initial_fdis(struct fd_info ***fdis, int enabled_buffers, list_head file_input_names, struct fd_ops *buffer_op, struct log_config *conf)
+{
+       assert(fdis);
+       assert(buffer_op);
+       assert(conf);
+
+       struct fd_info **fdi_ptrs = calloc(list_count(file_input_names) + bit_count(enabled_buffers) + 1 /* NULL terminator */, sizeof *fdi_ptrs);
+       if (!fdi_ptrs)
+               return -ENOMEM;
+
+       int fdi_cnt = 0;
+       int ret = 0;
+       for (int i = 0; i < LOG_ID_MAX; ++i) {
+               if (!bit_test(enabled_buffers, i))
+                       continue;
+
+               const char *const bufname = log_name_by_id(i);
+               struct fd_info *fdi;
+               switch (i) {
+               case LOG_ID_KMSG:
+               case LOG_ID_SYSLOG:
+                       fdi = fdi_create(&ops_pipe, bufname);
+                       break;
+               default:
+                       fdi = fdi_create(buffer_op, bufname);
+                       break;
+               }
+               if (!fdi) {
+                       ret = -ENOMEM;
+                       goto failure;
+               }
+
+               if (fdi->ops->create(fdi, conf, bufname) < 0) {
+                       printf("Unable to access buffer \"%s\"\n", bufname);
+                       fdi_free(fdi);
+                       continue;
+               }
+               fdi_ptrs[fdi_cnt++] = fdi;
+       }
+       if (enabled_buffers && !fdi_cnt) {
+               ret = -EINVAL;
+               goto failure;
+       }
+
+       for (list_head iter = file_input_names; iter; list_next(&iter)) {
+               const char *const filename = (const char *)list_at(iter);
+               struct fd_info *fdi = fdi_create(&ops_binfile, filename);
+               if (!fdi) {
+                       ret = -ENOMEM;
+                       goto failure;
+               }
+               if (fdi->ops->create(fdi, conf, filename) < 0) {
+                       printf("Unable to access file \"%s\"\n", filename);
+                       fdi_free(fdi);
+                       continue;
+               }
+               fdi_ptrs[fdi_cnt++] = fdi;
+       }
+
+       *fdis = fdi_ptrs;
+       return fdi_cnt;
+
+failure:
+
+       fdi_array_free(&fdi_ptrs);
+       return ret;
+}
+
 int main(int argc, char **argv)
 {
        int enabled_buffers = 0; // bitset
@@ -404,46 +472,43 @@ int main(int argc, char **argv)
                return 1;
        }
 
-       fdi_ptrs = calloc(list_count(file_input_names) + bit_count(enabled_buffers) + 1 /* NULL terminator */, sizeof *fdi_ptrs);
-       if (!fdi_ptrs) {
-               printf("Error not enough memory\n");
+       fdi_cnt = create_initial_fdis(&fdi_ptrs, enabled_buffers, file_input_names, !strcmp(conf_value, "pipe") ? &ops_pipe : &ops_logger, &conf);
+       if (fdi_cnt < 0) {
+               printf("Error creating fd info: %s\n", strerror(-fdi_cnt));
                return 1;
        }
 
-       for (i = 0; i < LOG_ID_MAX; ++i) {
-               if (!bit_test(enabled_buffers, i))
-                       continue;
+       for (i = 0; i < fdi_cnt; ++i) {
+               struct fd_info *const fdi = fdi_ptrs[i];
 
-               struct fd_info *fdi;
-               const char *const bufname = log_name_by_id(i);
-               if (!strcmp(conf_value, "pipe")
-                       || !strcmp(bufname, "syslog")
-                       || !strcmp(bufname, "kmsg"))
-                       fdi = process_buffer_pipe(bufname, action == ACTION_CLEAR, &conf, dump, filters, l_file.format);
-               else
-                       fdi = process_buffer_nonpipe(bufname, action == ACTION_CLEAR, &conf, filters, l_file.format);
-               if (fdi) {
-                       fdi_ptrs[fdi_cnt++] = fdi;
-                       if (bit_count(enabled_buffers) == 1 || !IS_VECTOR_SIZE_SORTABLE(logs.size))
-                               fdi->do_sorting = 0;
-               } else {
-                       printf("Unable to access buffer \"%s\"\n", bufname);
+               int r = 0;
+               switch (action) {
+               case ACTION_CLEAR:
+                       r = fdi->ops->clear(fdi);
+                       break;
+               case ACTION_PRINT: {
+                       r = fdi->ops->prepare_print(fdi, dump, filters, l_file.format);
+                       break;
+               } case ACTION_GETSIZE:
+                       // r = fdi->ops->getsize(fdi);
+                       break;
+               default:
+                       assert(false);
                }
-       }
-       if (bit_count(enabled_buffers) > 0 && !fdi_cnt)
-               return 1;
 
-       if (action == ACTION_CLEAR)
-               return 0;
-
-       for (list_head iter = file_input_names; iter; list_next(&iter)) {
-               struct fd_info *fdi = handle_file((const char *)list_at(iter));
-               if (!fdi)
+               if (r < 0) {
+                       static const char *action_names[] = {
+                               [ACTION_PRINT] = "preparing for printing",
+                               [ACTION_GETSIZE] = "size getting",
+                               [ACTION_CLEAR] = "buffer clearing",
+                       };
+                       printf("Error while %s: %s\n", action_names[action], strerror(-r));
                        return 1;
-               fdi_ptrs[fdi_cnt++] = fdi;
+               }
        }
 
-       handle_pipe(fdi_ptrs, fdi_cnt, dump, &logs, &l_file);
+       if (action == ACTION_PRINT)
+               do_print(fdi_ptrs, fdi_cnt, dump, &logs, &l_file);
 
        return 0;