diff options
author | Frederic Berat <fberat@de.adit-jv.com> | 2015-10-07 19:35:25 +0900 |
---|---|---|
committer | Lutz Helwing <lutz_helwing@mentor.com> | 2015-11-24 09:48:42 +0100 |
commit | 5574d46a4083d783a915688e0e05593b9558497b (patch) | |
tree | 27284c79587b1576703424fb68d71e09d552b259 /src/console/logstorage | |
parent | 8ed28dc15429a736c8404d491ed73fd0b04235e2 (diff) | |
download | DLT-daemon-5574d46a4083d783a915688e0e05593b9558497b.tar.gz |
Control application: Control appliction to support offline log storage trigger
Features :
1. One shot trigger with path
2. Automounter based trigger
3. Udev based trigger
Signed-off-by: Frederic Berat <fberat@de.adit-jv.com>
Signed-off-by: Christoph Lipka <clipka@jp.adit-jv.com>
Signed-off-by: anitha.ba <anithaammaji.baggam@in.bosch.com>
Signed-off-by: S. Hameed <shameed@jp.adit-jv.com>
Diffstat (limited to 'src/console/logstorage')
-rw-r--r-- | src/console/logstorage/CMakeLists.txt | 41 | ||||
-rw-r--r-- | src/console/logstorage/dlt-logstorage-common.c | 318 | ||||
-rw-r--r-- | src/console/logstorage/dlt-logstorage-common.h | 83 | ||||
-rw-r--r-- | src/console/logstorage/dlt-logstorage-ctrl.c | 551 | ||||
-rw-r--r-- | src/console/logstorage/dlt-logstorage-ctrl.h | 30 | ||||
-rw-r--r-- | src/console/logstorage/dlt-logstorage-list.c | 236 | ||||
-rw-r--r-- | src/console/logstorage/dlt-logstorage-list.h | 33 | ||||
-rw-r--r-- | src/console/logstorage/dlt-logstorage-prop.h | 72 | ||||
-rw-r--r-- | src/console/logstorage/dlt-logstorage-udev.c | 448 | ||||
-rw-r--r-- | src/console/logstorage/dlt-logstorage-udev.h | 39 |
10 files changed, 1851 insertions, 0 deletions
diff --git a/src/console/logstorage/CMakeLists.txt b/src/console/logstorage/CMakeLists.txt new file mode 100644 index 0000000..830bf5a --- /dev/null +++ b/src/console/logstorage/CMakeLists.txt @@ -0,0 +1,41 @@ +####### +# @licence make begin@ +# SPDX license identifier: MPL-2.0 +# +# Copyright (C) 2015, ADIT GmbH +# +# This file is part of GENIVI Project DLT - Diagnostic Log and Trace. +# +# This Source Code Form is subject to the terms of the +# Mozilla Public License (MPL), v. 2.0. +# If a copy of the MPL was not distributed with this file, +# You can obtain one at http://mozilla.org/MPL/2.0/. +# +# For further information see http://www.genivi.org/. +# @licence end@ +####### +add_definitions( -Werror ) + +if(WITH_DLT_LOGSTORAGE_CTRL_UDEV AND WITH_DLT_LOGSTORAGE_CTRL_PROP) + set(dlt_logstorage_ctrl_SRCS dlt-logstorage-ctrl.c dlt-logstorage-common.c dlt-logstorage-prop.c dlt-logstorage-udev.c dlt-logstorage-list.c) +elseif(WITH_DLT_LOGSTORAGE_CTRL_PROP) + set(dlt_logstorage_ctrl_SRCS dlt-logstorage-ctrl.c dlt-logstorage-common.c dlt-logstorage-prop.c dlt-logstorage-list.c) +elseif(WITH_DLT_LOGSTORAGE_CTRL_UDEV) + set(dlt_logstorage_ctrl_SRCS dlt-logstorage-ctrl.c dlt-logstorage-common.c dlt-logstorage-udev.c dlt-logstorage-list.c) +else(WITH_DLT_LOGSTORAGE_CTRL_UDEV) + set(dlt_logstorage_ctrl_SRCS dlt-logstorage-ctrl.c dlt-logstorage-common.c dlt-logstorage-list.c) +endif(WITH_DLT_LOGSTORAGE_CTRL_UDEV AND WITH_DLT_LOGSTORAGE_CTRL_PROP) + +add_executable(dlt-logstorage-ctrl ${dlt_logstorage_ctrl_SRCS} ${dlt_control_common_SRCS} ${dlt_most_SRCS} ${CMAKE_SOURCE_DIR}/systemd/3rdparty/sd-daemon.c ) + +if(WITH_DLT_LOGSTORAGE_CTRL_UDEV) + target_link_libraries(dlt-logstorage-ctrl dlt udev ${EXPAT_LIBRARIES}) +else(WITH_DLT_LOGSTORAGE_CTRL_UDEV) + target_link_libraries(dlt-logstorage-ctrl dlt ${EXPAT_LIBRARIES}) +endif(WITH_DLT_LOGSTORAGE_CTRL_UDEV) + +set_target_properties(dlt-logstorage-ctrl PROPERTIES LINKER_LANGUAGE C) + +install(TARGETS dlt-logstorage-ctrl + RUNTIME DESTINATION bin + COMPONENT base) diff --git a/src/console/logstorage/dlt-logstorage-common.c b/src/console/logstorage/dlt-logstorage-common.c new file mode 100644 index 0000000..a2f60a0 --- /dev/null +++ b/src/console/logstorage/dlt-logstorage-common.c @@ -0,0 +1,318 @@ +/** + * @licence app begin@ + * Copyright (C) 2013 - 2015 Advanced Driver Information Technology. + * This code is developed by Advanced Driver Information Technology. + * Copyright of Advanced Driver Information Technology, Bosch and DENSO. + * + * This file is part of GENIVI Project Dlt - Diagnostic Log and Trace console apps. + * + * + * \copyright + * This Source Code Form is subject to the terms of the + * Mozilla Public License, v. 2.0. If a copy of the MPL was not distributed with + * this file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * + * \author Syed Hameed <shameed@jp.adit-jv.com> ADIT 2013 - 2015 + * \author Christoph Lipka <clipka@jp.adit-jv.com> ADIT 2015 + * \author Frederic Berat <fberat@de.adit-jv.com> ADIT 2015 + * + * \file dlt-logstorage-common.c + * For further information see http://www.genivi.org/. + * @licence end@ + */ + +/******************************************************************************* +** ** +** SRC-MODULE: dlt-logstorage-common.c ** +** ** +** TARGET : linux ** +** ** +** PROJECT : DLT ** +** ** +** AUTHOR : Christoph Lipka clipka@jp.adit-jv.com ** +** Frederic Berat fberat@de.adit-jv.com ** +** PURPOSE : ** +** ** +** REMARKS : Code extracted from dlt-control-common.c and reworked. ** +** ** +** PLATFORM DEPENDANT [yes/no]: yes ** +** ** +** TO BE CHANGED BY USER [yes/no]: no ** +** ** +*******************************************************************************/ + +/******************************************************************************* +** Author Identity ** +******************************************************************************** +** ** +** Initials Name Company ** +** -------- ------------------------- ---------------------------------- ** +** cl Christoph Lipka ADIT ** +** fb Frederic Berat ADIT ** +*******************************************************************************/ +#define pr_fmt(fmt) "Logstorage common: "fmt + +#include <errno.h> +#include <dirent.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <pthread.h> +#include <sys/types.h> +#include <sys/socket.h> + +#include "dlt_common.h" +#include "dlt_protocol.h" +#include "dlt_client.h" + +#include "dlt-control-common.h" +#include "dlt-logstorage-common.h" + +#ifdef DLT_LOGSTORAGE_CTRL_UDEV_ENABLE +#include "dlt-logstorage-udev.h" +#endif + +#include "dlt-logstorage-prop.h" + +static struct LogstorageOptions { + int event_type; /**< EVENT_UNMOUNTING/EVENT_MOUNTED */ + char device_path[DLT_MOUNT_PATH_MAX]; /**< Default Mount path */ + DltLogstorageHandler handler_type; /**< be controlled by udev or prop */ + long timeout; /**< Default timeout */ +} g_options = { + .event_type = EVENT_MOUNTED, + .handler_type = CTRL_NOHANDLER, +}; + +DltLogstorageHandler get_handler_type(void) +{ + return g_options.handler_type; +} + +void set_handler_type(char *type) +{ + g_options.handler_type = CTRL_UDEV; + + if (type && check_proprietary_handling(type)) + { + g_options.handler_type = CTRL_PROPRIETARY; + } +} + +int get_default_event_type(void) +{ + return g_options.event_type; +} + +void set_default_event_type(long type) +{ + g_options.event_type = !!type; +} + +char *get_default_path(void) +{ + return g_options.device_path; +} + +void set_default_path(char *path) +{ + memset(g_options.device_path, 0, DLT_MOUNT_PATH_MAX); + strncpy(g_options.device_path, path, DLT_MOUNT_PATH_MAX - 1); +} + +/* Used by the handlers */ +static DltLogstorageCtrl lctrl; + +DltLogstorageCtrl *get_logstorage_control(void) +{ + return &lctrl; +} + +void *dlt_logstorage_get_handler_cb(void) +{ + return lctrl.callback; +} + +int dlt_logstorage_get_handler_fd(void) +{ + return lctrl.fd; +} + +/** @brief Initialized the handler based on configuration + * + * @return 0 on success, -1 otherwise. + */ +int dlt_logstorage_init_handler(void) +{ + switch (get_handler_type()) + { + case CTRL_PROPRIETARY: + return dlt_logstorage_prop_init(); + case CTRL_UDEV: + default: +#ifdef DLT_LOGSTORAGE_CTRL_UDEV_ENABLE + return dlt_logstorage_udev_init(); +#else + return -1; +#endif + } +} + +/** @brief Clean-up the handler based on configuration + * + * @return 0 on success, -1 otherwise. + */ +int dlt_logstorage_deinit_handler(void) +{ + switch (get_handler_type()) + { + case CTRL_PROPRIETARY: + return dlt_logstorage_prop_deinit(); + case CTRL_UDEV: + default: +#ifdef DLT_LOGSTORAGE_CTRL_UDEV_ENABLE + return dlt_logstorage_udev_deinit(); +#else + return -1; +#endif + } +} + +/** @brief Search for config file in given mount point + * + * The file is searched at the top directory. The function exits once it + * founds it. + * + * @param mnt_point The mount point to check + * + * @return 1 if the file is found, 0 otherwise. + */ +int dlt_logstorage_check_config_file(char *mnt_point) +{ + struct dirent **files; + int n; + int i = 0; + int ret = 0; + + if ((mnt_point == NULL) || (mnt_point[0] == '\0')) + { + pr_error("Mount point missing.\n"); + return ret; + } + + pr_verbose("Now scanning %s\n", mnt_point); + + n = scandir(mnt_point, &files, NULL, alphasort); + + if (n <= 0) + { + pr_error("Cannot read mounted directory\n"); + return ret; + } + + do + { + pr_verbose("Checking %s.\n", files[i]->d_name); + + if (strncmp(files[i]->d_name, CONF_NAME, strlen(CONF_NAME)) == 0) + { + /* We found it ! */ + pr_verbose("File found.\n"); + ret = 1; + break; + } + } + while (++i < n); + + for (i = 0 ; i < n ; i++) + { + free(files[i]); + } + + free(files); + return ret; +} + +/** @brief Prepares the body of the message to be send to DLT + * + * @param body A pointer to the MsgBody structure pointer + * @param conn_type The type of the event (Mounted/Unmounting) + * @param path The mount point path. + * + * @return The body once built or NULL. + */ +static DltControlMsgBody *prepare_message_body(DltControlMsgBody **body, + int conn_type, + char *path) +{ + DltServiceOfflineLogstorage *serv = NULL; + + if (path == NULL) + { + pr_error("Mount path is uninitialized: %s\n", path); + return NULL; + } + + pr_verbose("Sending event %d for %s.\n", conn_type, path); + + *body = calloc(1, sizeof(DltControlMsgBody)); + + if (!*body) + { + pr_error("Not able to allocate memory for body.\n"); + return *body; + } + + (*body)->data = calloc(1, sizeof(DltServiceOfflineLogstorage)); + + if (!(*body)->data) + { + free(*body); + *body = NULL; + pr_error("Not able to allocate memory for body data.\n"); + return NULL; + } + + (*body)->size = sizeof(DltServiceOfflineLogstorage); + + serv = (DltServiceOfflineLogstorage *) (*body)->data; + + serv->service_id = DLT_SERVICE_ID_OFFLINE_LOGSTORAGE; + serv->connection_type = conn_type; + /* mount_point is DLT_MOUNT_PATH_MAX + 1 long, + * and the memory is already zeroed. + */ + strncpy(serv->mount_point, path, DLT_MOUNT_PATH_MAX); + + pr_verbose("Body is now ready.\n"); + + return *body; +} + +/** @brief Send a logstorage event to DLT + * + * @param type The type of the event (Mounted/Unmounting) + * @param mount_point The mount point for this event + * + * @return 0 On success, -1 otherwise. + */ +int dlt_logstorage_send_event(int type, char *mount_point) +{ + int ret = 0; + DltControlMsgBody *msg_body = NULL; + + /* mount_point is checked against NULL in the preparation */ + if (!prepare_message_body(&msg_body, type, mount_point)) + { + pr_error("Data for Dlt Message body is NULL\n"); + return -1; + } + + ret = dlt_control_send_message(msg_body, get_timeout()); + + free(msg_body->data); + free(msg_body); + + return ret; +} diff --git a/src/console/logstorage/dlt-logstorage-common.h b/src/console/logstorage/dlt-logstorage-common.h new file mode 100644 index 0000000..712f2e3 --- /dev/null +++ b/src/console/logstorage/dlt-logstorage-common.h @@ -0,0 +1,83 @@ +/** + * @licence app begin@ + * Copyright (C) 2013 - 2015 Advanced Driver Information Technology. + * This code is developed by Advanced Driver Information Technology. + * Copyright of Advanced Driver Information Technology, Bosch and DENSO. + * + * This file is part of GENIVI Project Dlt - Diagnostic Log and Trace console apps. + * + * + * \copyright + * This Source Code Form is subject to the terms of the + * Mozilla Public License, v. 2.0. If a copy of the MPL was not distributed with + * this file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * + * \author Syed Hameed <shameed@jp.adit-jv.com> ADIT 2013 - 2015 + * \author Christoph Lipka <clipka@jp.adit-jv.com> ADIT 2015 + * \author Frederic Berat <fberat@de.adit-jv.com> ADIT 2015 + * + * \file dlt-logstorage-common.h + * For further information see http://www.genivi.org/. + * @licence end@ + */ + +#ifndef _DLT_LOGSTORAGE_COMMON_H_ +#define _DLT_LOGSTORAGE_COMMON_H_ + +#define CONF_NAME "dlt_logstorage.conf" + +#define EVENT_UNMOUNTING 0 +#define EVENT_MOUNTED 1 + +typedef enum +{ + CTRL_NOHANDLER = 0, /**< one shot application */ + CTRL_UDEV, /**< Handles udev events */ + CTRL_PROPRIETARY /**< Handles proprietary event */ +} DltLogstorageHandler; + +DltLogstorageHandler get_handler_type(void); +void set_handler_type(char *); + +char *get_default_path(void); +void set_default_path(char *); + +int get_default_event_type(void); +void set_default_event_type(long type); + +typedef struct { + int fd; + int (*callback)(void); /* callback for event handling */ + void *prvt; /* Private data */ +} DltLogstorageCtrl; + +/* Get a reference to the logstorage control instance */ +DltLogstorageCtrl *get_logstorage_control(void); +void *dlt_logstorage_get_handler_cb(void); +int dlt_logstorage_get_handler_fd(void); +int dlt_logstorage_init_handler(void); +int dlt_logstorage_deinit_handler(void); + +/** + * Send an event to the dlt daemon + * + * @param type Event type (EVENT_UNMOUNTING/EVENT_MOUNTED) + * @param mount_point The mount point path concerned by this event + * + * @return 0 on success, -1 on error + */ +int dlt_logstorage_send_event(int, char *); + +/** @brief Search for config file in given mount point + * + * The file is searched at the top directory. The function exits once it + * founds it. + * + * @param mnt_point The mount point to check + * + * @return 1 if the file is found, 0 otherwise. + */ +int dlt_logstorage_check_config_file(char *); + +#endif diff --git a/src/console/logstorage/dlt-logstorage-ctrl.c b/src/console/logstorage/dlt-logstorage-ctrl.c new file mode 100644 index 0000000..b4d2b92 --- /dev/null +++ b/src/console/logstorage/dlt-logstorage-ctrl.c @@ -0,0 +1,551 @@ +/** + * @licence app begin@ + * Copyright (C) 2013 - 2015 Advanced Driver Information Technology. + * This code is developed by Advanced Driver Information Technology. + * Copyright of Advanced Driver Information Technology, Bosch and DENSO. * + * This file is part of GENIVI Project Dlt - Diagnostic Log and Trace console apps. + * + * + * \copyright + * This Source Code Form is subject to the terms of the + * Mozilla Public License, v. 2.0. If a copy of the MPL was not distributed with + * this file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * + * \author Syed Hameed <shameed@jp.adit-jv.com> ADIT 2013 - 2015 + * \author Christoph Lipka <clipka@jp.adit-jv.com> ADIT 2015 + * \author Frederic Berat <fberat@de.adit-jv.com> ADIT 2015 + * + * \file dlt-logstorage-ctrl.c + * For further information see http://www.genivi.org/. + * @licence end@ + */ +/******************************************************************************* +** ** +** SRC-MODULE: dlt-logstorage-ctrl.c ** +** ** +** TARGET : linux ** +** ** +** PROJECT : DLT ** +** ** +** AUTHOR : Syed Hameed shameed@jp.adit-jv.com ** +** Christoph Lipka clipka@jp.adit-jv.com ** +** AnithaAmmaji.baggam@in.bosch.com ** +** Frederic Berat fberat@de.adit-jv.com ** +** PURPOSE : ** +** ** +** REMARKS : ** +** ** +** PLATFORM DEPENDANT [yes/no]: yes ** +** ** +** TO BE CHANGED BY USER [yes/no]: no ** +** ** +*******************************************************************************/ + +/******************************************************************************* +** Author Identity ** +******************************************************************************** +** Initials Name Company ** +** -------- ------------------------- ---------------------------------- ** +** sh Syed Hameed ADIT ** +** cl Christoph Lipka ADIT ** +** BA Anitha BA ADIT ** +** fb Frederic Berat ADIT ** +*******************************************************************************/ + +#define pr_fmt(fmt) "Logstorage control: "fmt + +#include <ctype.h> +#include <errno.h> +#include <stdio.h> +#include <stdlib.h> +#include <signal.h> +#include <string.h> + +#include <sys/epoll.h> + +#include "sd-daemon.h" + +#include "dlt_protocol.h" +#include "dlt_client.h" +#include "dlt-control-common.h" +#include "dlt-logstorage-common.h" +#include "dlt-logstorage-ctrl.h" + +#define EPOLL_MAX_EVENTS 10 +#define EPOLL_TIME_OUT 500 + +#define DLT_LOGSTORAGE_CTRL_EXIT 1 +static int must_exit; +static int efd; + +/** @brief Triggers the application exit + * + * The application will exit on next epoll timeout. + */ +void dlt_logstorage_exit(void) +{ + must_exit = DLT_LOGSTORAGE_CTRL_EXIT; +} + +/** @brief Check if the application must exit + * + * The application will exit on next epoll timeout. + */ +int dlt_logstorage_must_exit(void) +{ + return must_exit; +} + +/** @brief Signal handler. + * + * Triggers the exit of the application in case of specific signals + * + * @param signo The value of the signal received. + */ +static void catch_signal(int signo) +{ + if (signo) + { + pr_error("Signal %d received, exiting.", signo); + dlt_logstorage_exit(); + } +} + +/** @brief Install a handler for some signals + * + * Handler are installed on exit related signals. That allows to exit from + * the main loop gracefully. + */ +static void install_signal_handler(void) +{ + int signals[] = { SIGINT, SIGQUIT, SIGTERM, 0 }; + unsigned int i; + struct sigaction sa; + + pr_verbose("Installing signal handler.\n"); + + /* install a signal handler for the above listed signals */ + for (i = 0 ; signals[i] ; i++) + { + memset(&sa, 0, sizeof(sa)); + sa.sa_handler = catch_signal; + + if (sigaction(signals[i], &sa, NULL) < 0) + { + pr_error("Failed to install signal %u handler. Error: %s\n", + signals[i], strerror(errno)); + } + } +} + +#define MAX_RESPONSE_LENGTH 32 +/** @brief Analyze the daemon answer to a request + * + * This function checks whether if the daemon answered positively to + * the request or not. + * + * @param data The textual answer + * @param payload The answer payload + * @param len The answer payload length + * @return 0 on success, -1 otherwise. + */ +static int analyze_response(char *data, void *payload, int len) +{ + int ret = -1; + char resp_ok[MAX_RESPONSE_LENGTH] = { 0 }; + + if (data == NULL || payload == NULL) + { + return -1; + } + + /* satisfy compiler */ + payload = payload; + len = len; + + snprintf(resp_ok, + MAX_RESPONSE_LENGTH, + "service(%u), ok", + DLT_SERVICE_ID_OFFLINE_LOGSTORAGE); + + if (strncmp(data, resp_ok, strlen(resp_ok)) == 0) + { + ret = 0; + } + + pr_verbose("Response received: '%s'\n", data); + pr_verbose("Response expected: '%s'\n", resp_ok); + + return ret; +} + +/** @brief Add a new event to watch to the epoll instance + * + * This function could be exported to be used by udev/prop so that they can + * register several events. + * There is no remove function as the removal is done on efd closure. + * + * @param fd The file descriptor to watch + * @param cb The callback to be called on event. + * + * @return epoll_ctrl return value, or -1 on earlier failure. + */ +static int dlt_logstorage_ctrl_add_event(int fd, void *cb) +{ + struct epoll_event event; + + if ((fd < 0) || !cb) + { + pr_error("Wrong parameter to add event (%d %p)\n", fd, cb); + return -1; + } + + pr_verbose("Setting up the event handler with (%d, %p).\n", fd, cb); + + event.data.ptr = cb; + event.events = EPOLLIN | EPOLLET; + + return epoll_ctl(efd, EPOLL_CTL_ADD, fd, &event); +} + +/** @brief Main execution loop + * + * Waits on events from the epoll fd, and executes the callbacks retrieved + * back from the event structure. + * + * @return 0 on success, -1 otherwise. + */ +static int dlt_logstorage_ctrl_execute_event_loop(int efd) +{ + struct epoll_event *events; + int i; + int ret = 0; + int n = 0; + + events = calloc(10, sizeof(struct epoll_event)); + + if (!events) + { + pr_error("No memory available for events.\n"); + return -1; + } + + n = epoll_wait(efd, events, EPOLL_MAX_EVENTS, EPOLL_TIME_OUT); + + if (n < 0) + { + pr_error("epoll_wait error: %s\n", strerror(errno)); + + if (errno == EINTR) + { + /* Only exit if the daemon has received QUIT/INT/TERM */ + free(events); + return 0; + } + + free(events); + return -1; + } + + for (i = 0 ; i < n ; i++) + { + int (*callback)() = events[i].data.ptr; + + if (!(events[i].events & (EPOLLIN | EPOLLET))) + { + pr_error("Error while polling. Event received: 0x%x\n", + events[i].events); + /* We only support one event producer. + * Error means that this producer died. + */ + pr_error("Now closing fd and exiting.\n"); + close(events[i].data.fd); + dlt_logstorage_exit(); + ret = -1; + break; + } + + if (!callback) + { + pr_error("Callback not found, exiting.\n"); + dlt_logstorage_exit(); + ret = -1; + break; + } + + pr_verbose("Got new event, calling %p.\n", callback); + + if (callback() < 0) + { + pr_error("Error while calling the callback, exiting.\n"); + dlt_logstorage_exit(); + ret = -1; + break; + } + } + + free(events); + return ret; +} + +/** @brief Start event loop and receive messages from DLT. + * + * The function will first install the signal handler, + * then create the epoll instance, initialize the communication controller, + * initialize the event handler and finally start the polling. + * + * @return 0 on success, -1 on error + */ +static int dlt_logstorage_ctrl_setup_event_loop(void) +{ + int ret = 0; + + install_signal_handler(); + + pr_verbose("Creating epoll instance.\n"); + efd = epoll_create1(0); + + if (efd == -1) + { + pr_error("epoll_create error: %s\n", strerror(errno)); + dlt_logstorage_exit(); + return -errno; + } + + /* Initializing the communication with the daemon */ + while (dlt_control_init(analyze_response, get_ecuid(), get_verbosity()) && + !dlt_logstorage_must_exit()) + { + pr_error("Failed to initialize connection with the daemon.\n"); + pr_error("Retrying to connect in %lds.\n", get_timeout()); + sleep(get_timeout()); + } + + if (dlt_logstorage_must_exit()) + { + pr_verbose("Exiting.\n"); + return 0; + } + + pr_verbose("Initializing event generator.\n"); + + if (dlt_logstorage_init_handler() < 0) + { + pr_error("Failed to initialize handler.\n"); + dlt_control_deinit(); + return -1; + } + + if (dlt_logstorage_ctrl_add_event(dlt_logstorage_get_handler_fd(), + dlt_logstorage_get_handler_cb()) < 0) + { + pr_error("epoll_ctl error: %s\n", strerror(errno)); + dlt_logstorage_exit(); + } + + while (!dlt_logstorage_must_exit() && (ret == 0)) + { + ret = dlt_logstorage_ctrl_execute_event_loop(efd); + } + + /* Clean up */ + close(efd); + + dlt_logstorage_deinit_handler(); + dlt_control_deinit(); + + return ret; +} + +/** @brief Send a single command to DLT daemon and wait for response + * + * @return 0 on success, -1 otherwise. + */ +static int dlt_logstorage_ctrl_single_request() +{ + int ret = 0; + /* Check if a 'CONF_NAME' file is present at the given path */ + if (!dlt_logstorage_check_config_file(get_default_path())) + { + pr_error("No '%s' file available at: %s\n", + CONF_NAME, + get_default_path()); + return -1; + } + + /* Initializing the communication with the daemon */ + while (dlt_control_init(analyze_response, get_ecuid(), get_verbosity()) && + !dlt_logstorage_must_exit()) + { + pr_error("Failed to initialize connection with the daemon.\n"); + pr_error("Retrying to connect in %lds.\n", get_timeout()); + sleep(get_timeout()); + } + + pr_verbose("event type is [%d]\t device path is [%s]\n", + get_default_event_type(), + get_default_path()); + + ret = dlt_logstorage_send_event(get_default_event_type(), + get_default_path()); + + dlt_control_deinit(); + + return ret; +} + +/** @brief Print out the application help + */ +static void usage(void) +{ + printf("Usage: dlt-logstorage-ctrl [options]\n"); + printf("Send a trigger to DLT daemon to connect/disconnect" + "a certain logstorage device\n"); + printf("\n"); + printf("Options:\n"); + printf(" -c Connection type: connect = 1, disconnect = 0\n"); + printf(" -d[prop] Run as daemon: prop = use proprietary handler\n"); + printf(" 'prop' may be replaced by any meaningful word\n"); + printf(" -e Set ECU ID (Default: %s)\n", DLT_CTRL_DEFAULT_ECUID); + printf(" -h Usage\n"); + printf(" -p Mount point path\n"); + printf(" -t Specify connection timeout (Default: %ds)\n", + DLT_CTRL_TIMEOUT); + printf(" -v Set verbose flag (Default:%d)\n", get_verbosity()); +} + +/** @brief Parses the application arguments + * + * The arguments are parsed and saved in static structure for future use. + * + * @param argc The amount of arguments + * @param argv The table of arguments + * + * @return 0 on success, -1 otherwise + */ +static int parse_args(int argc, char *argv[]) +{ + int c = -1; + + while ((c = getopt(argc, argv, ":t:he:p:d::c:v")) != -1) + { + switch (c) + { + case 't': + set_timeout(strtol(optarg, NULL, 10)); + break; + case 'h': + usage(); + return -1; + case 'e': + set_ecuid(optarg); + break; + case 'd': + pr_verbose("Choosing handler.\n"); + set_handler_type(optarg); + pr_verbose("Handler chosen: %d.\n", get_handler_type()); + break; + case 'p': + + if (strlen(optarg) >= DLT_MOUNT_PATH_MAX) + { + pr_error("Mount path '%s' too long\n", optarg); + return -1; + } + + set_default_path(optarg); + break; + case 'c': + set_default_event_type(strtol(optarg, NULL, 10)); + break; + case 'v': + set_verbosity(1); + pr_verbose("Now in verbose mode.\n"); + break; + case ':': + pr_error("Option -%c requires an argument.\n", optopt); + usage(); + return -1; + case '?': + + if (isprint(optopt)) + { + pr_error("Unknown option -%c.\n", optopt); + } + else + { + pr_error("Unknown option character \\x%x.\n", optopt); + } + + usage(); + return -1; + default: + pr_error("Try %s -h for more information.\n", argv[0]); + return -1; + } + } + + return 0; +} + +/** @brief Entry point + * + * Execute the argument parser and call the main feature accordingly. + * + * @param argc The amount of arguments + * @param argv The table of arguments + * + * @return 0 on success, -1 otherwise + */ +int main(int argc, char *argv[]) +{ + int ret = 0; + + set_ecuid(DLT_CTRL_DEFAULT_ECUID); + set_timeout(DLT_CTRL_TIMEOUT); + + /* Get command line arguments */ + if (parse_args(argc, argv) != 0) + { + return -1; + } + + /* all parameter valid, start communication with daemon or setup + * communication with control daemon */ + if (get_handler_type() == CTRL_NOHANDLER) + { + pr_verbose("One shot.\n"); + + ret = dlt_logstorage_ctrl_single_request(); + if (ret < 0) + { + pr_error("Message failed to be send. Please check DLT config.\n"); + } + } + else + { + pr_verbose("Entering in daemon mode.\n"); + + /* Let's daemonize */ + if (sd_notify(0, "READY=1") <= 0) + { + pr_verbose("SD notify failed, manually daemonizing.\n"); + + /* No message can be sent or Systemd is not available. + * Daemonizing manually. + */ + if (daemon(1, 1)) + { + pr_error("Failed to daemonize: %s\n", strerror(errno)); + return EXIT_FAILURE; + } + } + + pr_verbose("Executing the event loop\n"); + ret = dlt_logstorage_ctrl_setup_event_loop(); + } + + pr_verbose("Exiting.\n"); + return ret; +} diff --git a/src/console/logstorage/dlt-logstorage-ctrl.h b/src/console/logstorage/dlt-logstorage-ctrl.h new file mode 100644 index 0000000..11abe10 --- /dev/null +++ b/src/console/logstorage/dlt-logstorage-ctrl.h @@ -0,0 +1,30 @@ +/** + * @licence app begin@ + * Copyright (C) 2013 - 2015 Advanced Driver Information Technology. + * This code is developed by Advanced Driver Information Technology. + * Copyright of Advanced Driver Information Technology, Bosch and DENSO. + * + * This file is part of GENIVI Project Dlt - Diagnostic Log and Trace console apps. + * + * + * \copyright + * This Source Code Form is subject to the terms of the + * Mozilla Public License, v. 2.0. If a copy of the MPL was not distributed with + * this file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * + * \author Syed Hameed <shameed@jp.adit-jv.com> ADIT 2013 - 2015 + * \author Christoph Lipka <clipka@jp.adit-jv.com> ADIT 2015 + * + * \file dlt-logstorage-ctrl.h + * For further information see http://www.genivi.org/. + * @licence end@ + */ + +#ifndef _DLT_LOGSTORAGE_CONTROL_H_ +#define _DLT_LOGSTORAGE_CONTROL_H_ + +/* Triggers the exit at the end of the event */ +void dlt_logstorage_exit(void); + +#endif diff --git a/src/console/logstorage/dlt-logstorage-list.c b/src/console/logstorage/dlt-logstorage-list.c new file mode 100644 index 0000000..0b7a8c0 --- /dev/null +++ b/src/console/logstorage/dlt-logstorage-list.c @@ -0,0 +1,236 @@ +/** + * @licence app begin@ + * Copyright (C) 2013 - 2015 Advanced Driver Information Technology. + * This code is developed by Advanced Driver Information Technology. + * Copyright of Advanced Driver Information Technology, Bosch and DENSO. + * + * This file is part of GENIVI Project Dlt - Diagnostic Log and Trace console apps. + * + * + * \copyright + * This Source Code Form is subject to the terms of the + * Mozilla Public License, v. 2.0. If a copy of the MPL was not distributed with + * this file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * + * \author Anitha.BA <anithaammaji.baggam@in.bosch.com> ADIT 2015 + * \author Christoph Lipka <clipka@jp.adit-jv.com> ADIT 2015 + * \author Frederic Berat <fberat@de.adit-jv.com> ADIT 2015 + * + * \file dlt-logstorage-list.c + * For further information see http://www.genivi.org/. + * @licence end@ + */ + +/******************************************************************************* +** ** +** SRC-MODULE: dlt-logstorage-list.c ** +** ** +** TARGET : linux ** +** ** +** PROJECT : DLT ** +** ** +** AUTHOR : Christoph Lipka clipka@jp.adit-jv.com ** +** Anitha.B.A anithaammaji.baggam@in.bosch.com ** +** Frederic Berat fberat@de.adit-jv.com ** +** ** +** PURPOSE : linked list implementation for storing the device info ** +** ** +** REMARKS : ** +** ** +** PLATFORM DEPENDANT [yes/no]: yes ** +** ** +** TO BE CHANGED BY USER [yes/no]: no ** +** ** +*******************************************************************************/ + +/******************************************************************************* +** Author Identity ** +******************************************************************************** +** ** +** Initials Name Company ** +** -------- ------------------------- ---------------------------------- ** +** BA Anitha ADIT ** +** cl Christoph Lipka ADIT ** +** fb Frederic Berat ADIT ** +*******************************************************************************/ +#define pr_fmt(fmt) "Log storage list: "fmt + +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <unistd.h> + +#include "dlt_common.h" +#include "dlt-control-common.h" +#include "dlt-logstorage-common.h" + +static struct LogstorageDeviceInfo +{ + char *dev_node; /**< The device node */ + char *mnt_point; /**< Mount point for this device */ + struct LogstorageDeviceInfo *prev; /**< Previous element of the list */ + struct LogstorageDeviceInfo *next; /**< Next element of the list */ +} *g_info; + +/** @brief Prints the device list in verbose mode + * + * This can be used to debug the behavior. + * Therefore, it's only available in verbose mode. + */ +void print_list() +{ + struct LogstorageDeviceInfo *ptr = g_info; + pr_verbose(" -------Device list-------\n"); + + while (ptr != NULL) + { + pr_verbose("%p:\t[%s][%s] \n", ptr, ptr->dev_node, ptr->mnt_point); + ptr = ptr->next; + } + + pr_verbose(" -------Device list end-------\n\n"); + + return; +} + +/** @brief Find element in the list based on device node + * + * Allows to check whether a device is already in the list or + * to find out the one to be removed. + * + * @param node The device node to look for + * + * @return The element of the list found, NULL either. + */ +static struct LogstorageDeviceInfo *logstorage_find_dev_info(const char *node) +{ + struct LogstorageDeviceInfo *ptr = g_info; + + if (!node) + { + return NULL; + } + + pr_verbose("Looking for %s.\n", node); + + while (ptr != NULL) + { + if (strncmp(ptr->dev_node, node, DLT_MOUNT_PATH_MAX) == 0) + { + pr_verbose("%s found in %p.\n", node, ptr); + break; + } + else + { + ptr = ptr->next; + } + } + + return ptr; +} + +/** @brief Add new device in the list + * + * The device is only added if a configuration file has been found and + * if it's not already in the list. + * + * @param node The device node to add + * @param path The corresponding mount point path + * + * @return 0 on success, -1 in case of error. + */ +int logstorage_store_dev_info(const char *node, const char *path) +{ + struct LogstorageDeviceInfo *ptr = NULL; + + if ((node == NULL) || (path == NULL)) + { + pr_error("Invalid input\n"); + return -1; + } + + if (logstorage_find_dev_info(node)) + { + pr_verbose("%s already in list.\n", node); + print_list(); + return 0; + } + + ptr = calloc(1, sizeof(struct LogstorageDeviceInfo)); + + if (ptr == NULL) + { + pr_error("Node creation failed\n"); + return -1; + } + + ptr->dev_node = strdup(node); + ptr->mnt_point = strndup(path, DLT_MOUNT_PATH_MAX); + + /* Put it on head */ + ptr->next = g_info; + + if (g_info) + { + g_info->prev = ptr; + } + + g_info = ptr; + + pr_verbose("%s added to list.\n", node); + print_list(); + + return 0; +} + +/** @brief Remove a device from the list + * + * If the device is removed from the list, the mount point + * pointer is given back to the caller. That means that + * he has to free it. + * + * @param node The device node to be removed + * + * @return the mount point if the node is found, NULL either. + */ +char *logstorage_delete_dev_info(const char *node) +{ + struct LogstorageDeviceInfo *del = NULL; + char *ret = NULL; + + del = logstorage_find_dev_info(node); + + if (del == NULL) + { + pr_verbose("%s not found in list.\n", node); + print_list(); + return ret; + } + + /* Has to be freed by the caller */ + ret = del->mnt_point; + + if (del->prev) + { + del->prev->next = del->next; + } + + if (del->next) + { + del->next->prev = del->prev; + } + + if (del == g_info) + { + g_info = g_info->next; + } + + free(del->dev_node); + free(del); + + pr_verbose("%s removed from list.\n", node); + print_list(); + + return ret; +} diff --git a/src/console/logstorage/dlt-logstorage-list.h b/src/console/logstorage/dlt-logstorage-list.h new file mode 100644 index 0000000..3df2171 --- /dev/null +++ b/src/console/logstorage/dlt-logstorage-list.h @@ -0,0 +1,33 @@ +/** + * @licence app begin@ + * Copyright (C) 2013 - 2015 Advanced Driver Information Technology. + * This code is developed by Advanced Driver Information Technology. + * Copyright of Advanced Driver Information Technology, Bosch and DENSO. + * + * This file is part of GENIVI Project Dlt - Diagnostic Log and Trace console apps. + * + * + * \copyright + * This Source Code Form is subject to the terms of the + * Mozilla Public License, v. 2.0. If a copy of the MPL was not distributed with + * this file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * + * \author Christoph Lipka clipka@jp.adit-jv.com + * \author Anitha BA <anithaammaji.baggam@in.bosch.com> ADIT 2015 + * \author Frederic Berat <fberat@de.adit-jv.com> ADIT 2015 + * + * \file dlt-logstorage-list.h + * For further information see http://www.genivi.org/. + * @licence end@ + */ + +#ifndef _DLT_LOGSTORAGE_LIST_H_ +#define _DLT_LOGSTORAGE_LIST_H_ + +/* Return 0 it the node as been added (or is already present) */ +int logstorage_store_dev_info(const char *node, const char *path); +/* Returns the mount point if node has been found and deleted. NULL either */ +char *logstorage_delete_dev_info(const char *node); + +#endif diff --git a/src/console/logstorage/dlt-logstorage-prop.h b/src/console/logstorage/dlt-logstorage-prop.h new file mode 100644 index 0000000..836dc99 --- /dev/null +++ b/src/console/logstorage/dlt-logstorage-prop.h @@ -0,0 +1,72 @@ +/** + * @licence app begin@ + * Copyright (C) 2013 - 2015 Advanced Driver Information Technology. + * This code is developed by Advanced Driver Information Technology. + * Copyright of Advanced Driver Information Technology, Bosch and DENSO. + * + * This file is part of GENIVI Project Dlt - Diagnostic Log and Trace console apps. + * + * \copyright + * This Source Code Form is subject to the terms of the + * Mozilla Public License, v. 2.0. If a copy of the MPL was not distributed with + * this file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * \author Christoph Lipka <clipka@jp.adit-jv.com> ADIT 2015 + * \author Frederic Berat <fberat@de.adit-jv.com> ADIT 2015 + * + * \file dlt-logstorage-udev.h + * For further information see http://www.genivi.org/. + * @licence end@ + */ + +#ifndef _DLT_LOGSTORAGE_PROP_H_ +#define _DLT_LOGSTORAGE_PROP_H_ + +#ifndef HAS_PROPRIETARY_LOGSTORAGE +/** @brief Initialize proprietary connection + * + * @return 0 + */ +static inline int dlt_logstorage_prop_init(void) { + return 0; +} + +/** @brief Clean-up proprietary connection + * + * @return 0 + */ +static inline int dlt_logstorage_prop_deinit(void) { + return 0; +} + +/** @brief Check whether user wants to use proprietary handler + * + * @return 0 + */ +static inline int check_proprietary_handling(char *type) { + (void)type; return 0; +} +#else +/** + * Initialize proprietary connection + * + * @return 0 on success, -1 on error + */ +int dlt_logstorage_prop_init(void); + +/** + * Clean-up proprietary connection + * + * @return 0 on success, -1 on error + */ +int dlt_logstorage_prop_deinit(void); + +/** + * Check whether user wants to use proprietary event handler + * + * @return 1 if yes, 0 either. + */ +int check_proprietary_handling(char *); +#endif /* HAS_PROPRIETARY_LOGSTORAGE */ + +#endif /* _DLT_LOGSTORAGE_PROP_H_ */ diff --git a/src/console/logstorage/dlt-logstorage-udev.c b/src/console/logstorage/dlt-logstorage-udev.c new file mode 100644 index 0000000..355977e --- /dev/null +++ b/src/console/logstorage/dlt-logstorage-udev.c @@ -0,0 +1,448 @@ +/** + * @licence app begin@ + * Copyright (C) 2013 - 2015 Advanced Driver Information Technology. + * This code is developed by Advanced Driver Information Technology. + * Copyright of Advanced Driver Information Technology, Bosch and DENSO. + * + * This file is part of GENIVI Project Dlt - Diagnostic Log and Trace console apps. + * + * + * \copyright + * This Source Code Form is subject to the terms of the + * Mozilla Public License, v. 2.0. If a copy of the MPL was not distributed with + * this file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * + * \author Christoph Lipka <clipka@jp.adit-jv.com> ADIT 2015 + * \author Frederic Berat <fberat@de.adit-jv.com> ADIT 2015 + * + * \file dlt-logstorage-udev.c + * For further information see http://www.genivi.org/. + * @licence end@ + */ + +/******************************************************************************* +** ** +** SRC-MODULE: dlt-logstorage-udev.c ** +** ** +** TARGET : linux ** +** ** +** PROJECT : DLT ** +** ** +** AUTHOR : Christoph Lipka clipka@jp.adit-jv.com ** +** Frederic Berat fberat@de.adit-jv.com ** +** ** +** PURPOSE : For udev-based handling of any device ** +** ** +** REMARKS : ** +** ** +** PLATFORM DEPENDANT [yes/no]: yes ** +** ** +** TO BE CHANGED BY USER [yes/no]: no ** +** ** +*******************************************************************************/ + +/******************************************************************************* +** Author Identity ** +******************************************************************************** +** ** +** Initials Name Company ** +** -------- ------------------------- ---------------------------------- ** +** cl Christoph Lipka ADIT ** +** fb Frederic Berat ADIT ** +*******************************************************************************/ + +#define pr_fmt(fmt) "Udev control: "fmt + +#include <libudev.h> +#include <errno.h> +#include <mntent.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <unistd.h> + +#include <sys/mount.h> + +#include "dlt-control-common.h" +#include "dlt-logstorage-common.h" +#include "dlt-logstorage-list.h" +#include "dlt-logstorage-udev.h" + +typedef struct { + struct udev *udev; /**< Udev instance */ + struct udev_monitor *mon; /**< Udev monitor instance */ +} LogstorageCtrlUdev; + +/** @brief Get mount point of a device node + * + * This function search for the mount point in /proc/mounts + * based on the device node. + * + * @param dev_node Device node as string + * + * @return mount path or NULL on error + */ +static char *dlt_logstorage_udev_get_mount_point(char *dev_node) +{ + struct mntent *ent; + FILE *f; + char *mnt_point = NULL; + + if (dev_node == NULL) + { + return NULL; + } + + f = setmntent("/proc/mounts", "r"); + + if (f == NULL) + { + pr_error("Cannot read /proc/mounts\n"); + return NULL; + } + + while (NULL != (ent = getmntent(f))) + { + if (strncmp(ent->mnt_fsname, dev_node, strlen(ent->mnt_fsname)) == 0) + { + mnt_point = strdup(ent->mnt_dir); + + /* Remounting rw */ + if (strlen(mnt_point)) + { + /* capabilities needed. Thus we don't really car on failure. + * Therefor we can ignore the return value. + */ + (void) mount(NULL, mnt_point, NULL, MS_REMOUNT, ent->mnt_opts); + } + + break; + } + } + + endmntent(f); + + return mnt_point; +} + +/** @brief Check if the daemon needs to be notified by the event + * + * On mount event: + * If the device mount point contains the DLT configuration file, + * the function will then send a message to the daemon. + * On Unmounting event: + * Check if the device was on the list, remove it and send the message + * to the daemon. + * + * @event The kind of event happening + * @part The device partition to be checked + * + * @return 0 on success, -1 if an error occured. + */ +static int check_mountpoint_from_partition(int event, struct udev_device *part) +{ + int logstorage_dev = 0; + char *mnt_point = NULL; + char *dev_node = NULL; + int ret = 0; + + if (!part) + { + pr_verbose("No partition structure given.\n"); + return -1; + } + + pr_verbose("Checking mount point.\n"); + + if (!udev_device_get_devnode(part)) + { + pr_verbose("Skipping as no devnode.\n"); + return 0; + } + + dev_node = strdup(udev_device_get_devnode(part)); + + if (event == EVENT_MOUNTED) + { + mnt_point = dlt_logstorage_udev_get_mount_point(dev_node); + logstorage_dev = dlt_logstorage_check_config_file(mnt_point); + + if (logstorage_dev) /* Configuration file available, add node to internal list */ + { + logstorage_store_dev_info(dev_node, mnt_point); + } + else + { + mnt_point = NULL; + } + } + else + { + /* remove device information */ + mnt_point = logstorage_delete_dev_info(dev_node); + } + + if (mnt_point) + { + ret = dlt_logstorage_send_event(event, mnt_point); + + if (ret) + { + pr_error("Can't send event for %s to DLT.\n", mnt_point); + } + } + + free(dev_node); + free(mnt_point); + + return 0; +} + +/** @brief Handles the udev events + * + * On event, it finds the corresponding action, and calls + * check_mountpoint_from_partition with the corresponding event. + * + * @return 0 on success, -1 on error. + */ +static int logstorage_udev_udevd_callback(void) +{ + const char *action; + int ret = 0; + DltLogstorageCtrl *lctrl = get_logstorage_control(); + LogstorageCtrlUdev *prvt = NULL; + struct udev_device *partition = NULL; + + if (!lctrl) + { + pr_error("Not able to get logstorage control instance.\n"); + return -1; + } + + prvt = (LogstorageCtrlUdev *)lctrl->prvt; + + if (!prvt || !prvt->mon) + { + pr_error("Not able to get private data.\n"); + return -1; + } + + partition = udev_monitor_receive_device(prvt->mon); + + if (!partition) + { + pr_error("Not able to get partition.\n"); + return -1; + } + + action = udev_device_get_action(partition); + + if (!action) + { + pr_error("Not able to get action.\n"); + udev_device_unref(partition); + return -1; + } + + pr_verbose("%s action received from udev for %s.\n", + action, + udev_device_get_devnode(partition)); + + if (strncmp(action, "add", sizeof("add")) == 0) + { + /*TODO: This can be replaced by polling on /proc/mount. + * we could get event on modification, and keep track on a list + * of mounted devices. New devices could be check that way. + * That also would solve the unmount event issue. + * Then, udev is only interesting to simplify the check on new devices, + * and/or for hot unplug (without unmount). + */ + usleep(500 * 1000); + ret = check_mountpoint_from_partition(EVENT_MOUNTED, partition); + } + else if (strncmp(action, "remove", sizeof("remove")) == 0) + { + ret = check_mountpoint_from_partition(EVENT_UNMOUNTING, partition); + } + + udev_device_unref(partition); + + return ret; +} + +/** @brief Check all partitions on the system to find configuration file + * + * The function looks for block devices that are of "partition" type. + * Then, it gets the node, and call check_mountpoint_from_partition with it. + * + * @udev The udev device used to find all the nodes + * + * @return 0 on success, -1 otherwise. + */ +static int dlt_logstorage_udev_check_mounted(struct udev *udev) +{ + /* Create a list of the devices in the 'partition' subsystem. */ + struct udev_enumerate *enumerate = udev_enumerate_new(udev); + struct udev_list_entry *devices = NULL; + struct udev_list_entry *dev_list_entry = NULL; + + if (!enumerate) + { + pr_error("Can't enumerate devices.\n"); + return -1; + } + + udev_enumerate_add_match_subsystem(enumerate, "block"); + udev_enumerate_add_match_property(enumerate, "DEVTYPE", "partition"); + udev_enumerate_scan_devices(enumerate); + + devices = udev_enumerate_get_list_entry(enumerate); + + /* For each list entry, get the corresponding device */ + udev_list_entry_foreach(dev_list_entry, devices) { + const char *path; + struct udev_device *partition = NULL; + + /* Get the filename of the /sys entry for the device + * and create a udev_device object representing it + */ + path = udev_list_entry_get_name(dev_list_entry); + partition = udev_device_new_from_syspath(udev, path); + + if (!partition) + { + continue; + } + + pr_verbose("Found device %s %s %s.\n", + path, + udev_device_get_devnode(partition), + udev_device_get_devtype(partition)); + + /* Check the device and clean-up */ + check_mountpoint_from_partition(EVENT_MOUNTED, partition); + udev_device_unref(partition); + } + + /* Free the enumerator object */ + udev_enumerate_unref(enumerate); + + return 0; +} + +/** @brief Clean-up the udev data + * + * That will destroy all the private data. + * + * @return 0 on success, -1 otherwise. + */ +int dlt_logstorage_udev_deinit(void) +{ + DltLogstorageCtrl *lctrl = get_logstorage_control(); + LogstorageCtrlUdev *prvt = NULL; + + if (!lctrl) + { + return -1; + } + + prvt = (LogstorageCtrlUdev *)lctrl->prvt; + + if (prvt->mon) + { + udev_monitor_unref(prvt->mon); + } + + if (prvt->udev) + { + udev_unref(prvt->udev); + } + + free(prvt); + lctrl->prvt = NULL; + + return 0; +} + +/** @brief Initialize the private data + * + * That function will create the udev device and monitor. + * + * @return 0 on success, -1 otherwise. + */ +int dlt_logstorage_udev_init(void) +{ + int ret = 0; + + DltLogstorageCtrl *lctrl = get_logstorage_control(); + LogstorageCtrlUdev *prvt = NULL; + + pr_verbose("Initializing.\n"); + + if (!lctrl) + { + pr_error("Not able to get logstorage control instance.\n"); + return -1; + } + + lctrl->prvt = calloc(1, sizeof(LogstorageCtrlUdev)); + + if (!lctrl->prvt) + { + pr_error("No memory to allocate private data.\n"); + return -1; + } + + prvt = (LogstorageCtrlUdev *)lctrl->prvt; + + /* Initialize udev object */ + prvt->udev = udev_new(); + + if (!prvt->udev) + { + pr_error("Cannot initialize udev object\n"); + dlt_logstorage_udev_deinit(); + return -1; + } + + /* setup udev monitor which will report events when + * devices attached to the system change. Events include + * "add", "remove", "change", etc */ + prvt->mon = udev_monitor_new_from_netlink(prvt->udev, "udev"); + + if (!prvt->mon) + { + pr_error("Cannot initialize udev monitor\n"); + dlt_logstorage_udev_deinit(); + return -1; + } + + ret = udev_monitor_filter_add_match_subsystem_devtype(prvt->mon, + "block", + NULL); + + if (ret) + { + pr_error("Cannot attach filter to monitor: %s.\n", strerror(-ret)); + dlt_logstorage_udev_deinit(); + return -1; + } + + ret = udev_monitor_enable_receiving(prvt->mon); + + if (ret < 0) + { + pr_error("Cannot start receiving: %s.\n", strerror(-ret)); + dlt_logstorage_udev_deinit(); + return -1; + } + + /* get file descriptor */ + lctrl->fd = udev_monitor_get_fd(prvt->mon); + /* set callback function */ + lctrl->callback = &logstorage_udev_udevd_callback; + + /* check if there is something already mounted */ + return dlt_logstorage_udev_check_mounted(prvt->udev); +} diff --git a/src/console/logstorage/dlt-logstorage-udev.h b/src/console/logstorage/dlt-logstorage-udev.h new file mode 100644 index 0000000..d202453 --- /dev/null +++ b/src/console/logstorage/dlt-logstorage-udev.h @@ -0,0 +1,39 @@ +/** + * @licence app begin@ + * Copyright (C) 2013 - 2015 Advanced Driver Information Technology. + * This code is developed by Advanced Driver Information Technology. + * Copyright of Advanced Driver Information Technology, Bosch and DENSO. + * + * This file is part of GENIVI Project Dlt - Diagnostic Log and Trace console apps. + * + * \copyright + * This Source Code Form is subject to the terms of the + * Mozilla Public License, v. 2.0. If a copy of the MPL was not distributed with + * this file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * \author Christoph Lipka <clipka@jp.adit-jv.com> ADIT 2015 + * \author Frederic Berat <fberat@de.adit-jv.com> ADIT 2015 + * + * \file dlt-logstorage-udev.h + * For further information see http://www.genivi.org/. + * @licence end@ + */ + +#ifndef _DLT_LOGSTORAGE_UDEV_H_ +#define _DLT_LOGSTORAGE_UDEV_H_ + +/** + * Initialize udev connection + * + * @return 0 on success, -1 on error + */ +int dlt_logstorage_udev_init(void); + +/** + * Clean-up udev connection + * + * @return 0 on success, -1 on error + */ +int dlt_logstorage_udev_deinit(void); + +#endif |