summaryrefslogtreecommitdiff
path: root/daemons/dmeventd/libdevmapper-event.c
diff options
context:
space:
mode:
Diffstat (limited to 'daemons/dmeventd/libdevmapper-event.c')
-rw-r--r--daemons/dmeventd/libdevmapper-event.c484
1 files changed, 307 insertions, 177 deletions
diff --git a/daemons/dmeventd/libdevmapper-event.c b/daemons/dmeventd/libdevmapper-event.c
index 1f8fbef..b5ae37f 100644
--- a/daemons/dmeventd/libdevmapper-event.c
+++ b/daemons/dmeventd/libdevmapper-event.c
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2005-2007 Red Hat, Inc. All rights reserved.
+ * Copyright (C) 2005-2015 Red Hat, Inc. All rights reserved.
*
* This file is part of the device-mapper userspace tools.
*
@@ -9,27 +9,28 @@
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program; if not, write to the Free Software Foundation,
- * Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
-#include "dmlib.h"
#include "libdevmapper-event.h"
-//#include "libmultilog.h"
#include "dmeventd.h"
+#include "libdm/misc/dm-logging.h"
+#include "base/memory/zalloc.h"
+
+#include "lib/misc/intl.h"
-#include <errno.h>
#include <fcntl.h>
-#include <stdio.h>
-#include <stdint.h>
-#include <stdlib.h>
-#include <string.h>
#include <sys/file.h>
#include <sys/types.h>
#include <sys/stat.h>
-#include <unistd.h>
#include <sys/wait.h>
#include <arpa/inet.h> /* for htonl, ntohl */
+#include <pthread.h>
+#include <syslog.h>
+#include <unistd.h>
+static int _debug_level = 0;
+static int _use_syslog = 0;
static int _sequence_nr = 0;
struct dm_event_handler {
@@ -49,17 +50,17 @@ struct dm_event_handler {
static void _dm_event_handler_clear_dev_info(struct dm_event_handler *dmevh)
{
- dm_free(dmevh->dev_name);
- dm_free(dmevh->uuid);
+ free(dmevh->dev_name);
+ free(dmevh->uuid);
dmevh->dev_name = dmevh->uuid = NULL;
dmevh->major = dmevh->minor = 0;
}
struct dm_event_handler *dm_event_handler_create(void)
{
- struct dm_event_handler *dmevh = NULL;
+ struct dm_event_handler *dmevh;
- if (!(dmevh = dm_zalloc(sizeof(*dmevh)))) {
+ if (!(dmevh = zalloc(sizeof(*dmevh)))) {
log_error("Failed to allocate event handler.");
return NULL;
}
@@ -70,9 +71,9 @@ struct dm_event_handler *dm_event_handler_create(void)
void dm_event_handler_destroy(struct dm_event_handler *dmevh)
{
_dm_event_handler_clear_dev_info(dmevh);
- dm_free(dmevh->dso);
- dm_free(dmevh->dmeventd_path);
- dm_free(dmevh);
+ free(dmevh->dso);
+ free(dmevh->dmeventd_path);
+ free(dmevh);
}
int dm_event_handler_set_dmeventd_path(struct dm_event_handler *dmevh, const char *dmeventd_path)
@@ -80,10 +81,9 @@ int dm_event_handler_set_dmeventd_path(struct dm_event_handler *dmevh, const cha
if (!dmeventd_path) /* noop */
return 0;
- dm_free(dmevh->dmeventd_path);
+ free(dmevh->dmeventd_path);
- dmevh->dmeventd_path = dm_strdup(dmeventd_path);
- if (!dmevh->dmeventd_path)
+ if (!(dmevh->dmeventd_path = strdup(dmeventd_path)))
return -ENOMEM;
return 0;
@@ -93,10 +93,10 @@ int dm_event_handler_set_dso(struct dm_event_handler *dmevh, const char *path)
{
if (!path) /* noop */
return 0;
- dm_free(dmevh->dso);
- dmevh->dso = dm_strdup(path);
- if (!dmevh->dso)
+ free(dmevh->dso);
+
+ if (!(dmevh->dso = strdup(path)))
return -ENOMEM;
return 0;
@@ -109,9 +109,9 @@ int dm_event_handler_set_dev_name(struct dm_event_handler *dmevh, const char *de
_dm_event_handler_clear_dev_info(dmevh);
- dmevh->dev_name = dm_strdup(dev_name);
- if (!dmevh->dev_name)
+ if (!(dmevh->dev_name = strdup(dev_name)))
return -ENOMEM;
+
return 0;
}
@@ -122,9 +122,9 @@ int dm_event_handler_set_uuid(struct dm_event_handler *dmevh, const char *uuid)
_dm_event_handler_clear_dev_info(dmevh);
- dmevh->uuid = dm_strdup(uuid);
- if (!dmevh->uuid)
+ if (!(dmevh->uuid = strdup(uuid)))
return -ENOMEM;
+
return 0;
}
@@ -201,7 +201,7 @@ static int _check_message_id(struct dm_event_daemon_message *msg)
if ((sscanf(msg->data, "%d:%d", &pid, &seq_nr) != 2) ||
(pid != getpid()) || (seq_nr != _sequence_nr)) {
log_error("Ignoring out-of-sequence reply from dmeventd. "
- "Expected %d:%d but received %s", getpid(),
+ "Expected %d:%d but received %s.", getpid(),
_sequence_nr, msg->data);
return 0;
}
@@ -224,7 +224,6 @@ static int _daemon_read(struct dm_event_fifos *fifos,
unsigned bytes = 0;
int ret, i;
fd_set fds;
- struct timeval tval = { 0, 0 };
size_t size = 2 * sizeof(uint32_t); /* status + size */
uint32_t *header = alloca(size);
char *buf = (char *)header;
@@ -232,66 +231,69 @@ static int _daemon_read(struct dm_event_fifos *fifos,
while (bytes < size) {
for (i = 0, ret = 0; (i < 20) && (ret < 1); i++) {
/* Watch daemon read FIFO for input. */
+ struct timeval tval = { .tv_sec = 1 };
FD_ZERO(&fds);
FD_SET(fifos->server, &fds);
- tval.tv_sec = 1;
- ret = select(fifos->server + 1, &fds, NULL, NULL,
- &tval);
+ ret = select(fifos->server + 1, &fds, NULL, NULL, &tval);
if (ret < 0 && errno != EINTR) {
- log_error("Unable to read from event server");
- return 0;
+ log_error("Unable to read from event server.");
+ goto bad;
}
if ((ret == 0) && (i > 4) && !bytes) {
log_error("No input from event server.");
- return 0;
+ goto bad;
}
}
if (ret < 1) {
log_error("Unable to read from event server.");
- return 0;
+ goto bad;
}
ret = read(fifos->server, buf + bytes, size);
if (ret < 0) {
if ((errno == EINTR) || (errno == EAGAIN))
continue;
- else {
- log_error("Unable to read from event server.");
- return 0;
- }
+
+ log_error("Unable to read from event server.");
+ goto bad;
}
bytes += ret;
- if (header && (bytes == 2 * sizeof(uint32_t))) {
+ if (!msg->data && (bytes == 2 * sizeof(uint32_t))) {
msg->cmd = ntohl(header[0]);
- msg->size = ntohl(header[1]);
- buf = msg->data = dm_malloc(msg->size);
- size = msg->size;
bytes = 0;
- header = 0;
+
+ if (!(size = msg->size = ntohl(header[1])))
+ break;
+
+ if (!(buf = msg->data = malloc(msg->size))) {
+ log_error("Unable to allocate message data.");
+ return 0;
+ }
}
}
- if (bytes != size) {
- dm_free(msg->data);
- msg->data = NULL;
- }
- return bytes == size;
+ if (bytes == size)
+ return 1;
+
+bad:
+ free(msg->data);
+ msg->data = NULL;
+
+ return 0;
}
/* Write message to daemon. */
static int _daemon_write(struct dm_event_fifos *fifos,
struct dm_event_daemon_message *msg)
{
- unsigned bytes = 0;
- int ret = 0;
+ int ret;
fd_set fds;
-
+ size_t bytes = 0;
size_t size = 2 * sizeof(uint32_t) + msg->size;
uint32_t *header = alloca(size);
char *buf = (char *)header;
char drainbuf[128];
- struct timeval tval = { 0, 0 };
header[0] = htonl(msg->cmd);
header[1] = htonl(msg->size);
@@ -299,17 +301,25 @@ static int _daemon_write(struct dm_event_fifos *fifos,
/* drain the answer fifo */
while (1) {
+ struct timeval tval = { .tv_usec = 100 };
FD_ZERO(&fds);
FD_SET(fifos->server, &fds);
- tval.tv_usec = 100;
ret = select(fifos->server + 1, &fds, NULL, NULL, &tval);
- if ((ret < 0) && (errno != EINTR)) {
- log_error("Unable to talk to event daemon");
+ if (ret < 0) {
+ if (errno == EINTR)
+ continue;
+ log_error("Unable to talk to event daemon.");
return 0;
}
if (ret == 0)
break;
- ret = read(fifos->server, drainbuf, 127);
+ ret = read(fifos->server, drainbuf, sizeof(drainbuf));
+ if (ret < 0) {
+ if ((errno == EINTR) || (errno == EAGAIN))
+ continue;
+ log_error("Unable to talk to event daemon.");
+ return 0;
+ }
}
while (bytes < size) {
@@ -319,7 +329,7 @@ static int _daemon_write(struct dm_event_fifos *fifos,
FD_SET(fifos->client, &fds);
ret = select(fifos->client + 1, NULL, &fds, NULL, NULL);
if ((ret < 0) && (errno != EINTR)) {
- log_error("Unable to talk to event daemon");
+ log_error("Unable to talk to event daemon.");
return 0;
}
} while (ret < 1);
@@ -328,10 +338,9 @@ static int _daemon_write(struct dm_event_fifos *fifos,
if (ret < 0) {
if ((errno == EINTR) || (errno == EAGAIN))
continue;
- else {
- log_error("Unable to talk to event daemon");
- return 0;
- }
+
+ log_error("Unable to talk to event daemon.");
+ return 0;
}
bytes += ret;
@@ -345,9 +354,6 @@ int daemon_talk(struct dm_event_fifos *fifos,
const char *dso_name, const char *dev_name,
enum dm_event_mask evmask, uint32_t timeout)
{
- const char *dso = dso_name ? dso_name : "-";
- const char *dev = dev_name ? dev_name : "-";
- const char *fmt = "%d:%d %s %s %u %" PRIu32;
int msg_size;
memset(msg, 0, sizeof(*msg));
@@ -355,14 +361,17 @@ int daemon_talk(struct dm_event_fifos *fifos,
* Set command and pack the arguments
* into ASCII message string.
*/
- msg->cmd = cmd;
- if (cmd == DM_EVENT_CMD_HELLO)
- fmt = "%d:%d HELLO";
- if ((msg_size = dm_asprintf(&(msg->data), fmt, getpid(), _sequence_nr,
- dso, dev, evmask, timeout)) < 0) {
- log_error("_daemon_talk: message allocation failed");
+ if ((msg_size =
+ ((cmd == DM_EVENT_CMD_HELLO) ?
+ dm_asprintf(&(msg->data), "%d:%d HELLO", getpid(), _sequence_nr) :
+ dm_asprintf(&(msg->data), "%d:%d %s %s %u %" PRIu32,
+ getpid(), _sequence_nr,
+ dso_name ? : "-", dev_name ? : "-", evmask, timeout)))
+ < 0) {
+ log_error("_daemon_talk: message allocation failed.");
return -ENOMEM;
}
+ msg->cmd = cmd;
msg->size = msg_size;
/*
@@ -371,15 +380,14 @@ int daemon_talk(struct dm_event_fifos *fifos,
*/
if (!_daemon_write(fifos, msg)) {
stack;
- dm_free(msg->data);
- msg->data = 0;
+ free(msg->data);
+ msg->data = NULL;
return -EIO;
}
do {
-
- dm_free(msg->data);
- msg->data = 0;
+ free(msg->data);
+ msg->data = NULL;
if (!_daemon_read(fifos, msg)) {
stack;
@@ -412,28 +420,56 @@ static int _start_daemon(char *dmeventd_path, struct dm_event_fifos *fifos)
char default_dmeventd_path[] = DMEVENTD_PATH;
char *args[] = { dmeventd_path ? : default_dmeventd_path, NULL };
- if (stat(fifos->client_path, &statbuf))
- goto start_server;
+ /*
+ * FIXME Explicitly verify the code's requirement that client_path is secure:
+ * - All parent directories owned by root without group/other write access unless sticky.
+ */
- if (!S_ISFIFO(statbuf.st_mode)) {
- log_error("%s is not a fifo.", fifos->client_path);
+ /* If client fifo path exists, only use it if it is root-owned fifo mode 0600 */
+ if ((lstat(fifos->client_path, &statbuf) < 0)) {
+ if (errno == ENOENT)
+ /* Jump ahead if fifo does not already exist. */
+ goto start_server;
+ else {
+ log_sys_error("stat", fifos->client_path);
+ return 0;
+ }
+ } else if (!S_ISFIFO(statbuf.st_mode)) {
+ log_error("%s must be a fifo.", fifos->client_path);
+ return 0;
+ } else if (statbuf.st_uid) {
+ log_error("%s must be owned by uid 0.", fifos->client_path);
+ return 0;
+ } else if (statbuf.st_mode & (S_IEXEC | S_IRWXG | S_IRWXO)) {
+ log_error("%s must have mode 0600.", fifos->client_path);
return 0;
}
/* Anyone listening? If not, errno will be ENXIO */
fifos->client = open(fifos->client_path, O_WRONLY | O_NONBLOCK);
if (fifos->client >= 0) {
+ /* Should never happen if all the above checks passed. */
+ if ((fstat(fifos->client, &statbuf) < 0) ||
+ !S_ISFIFO(statbuf.st_mode) || statbuf.st_uid ||
+ (statbuf.st_mode & (S_IEXEC | S_IRWXG | S_IRWXO))) {
+ log_error("%s is no longer a secure root-owned fifo with mode 0600.", fifos->client_path);
+ if (close(fifos->client))
+ log_sys_debug("close", fifos->client_path);
+ return 0;
+ }
+
/* server is running and listening */
if (close(fifos->client))
- log_sys_error("close", fifos->client_path);
+ log_sys_debug("close", fifos->client_path);
return 1;
- } else if (errno != ENXIO) {
+ }
+ if (errno != ENXIO && errno != ENOENT) {
/* problem */
log_sys_error("open", fifos->client_path);
return 0;
}
- start_server:
+start_server:
/* server is not running */
if ((args[0][0] == '/') && stat(args[0], &statbuf)) {
@@ -448,11 +484,11 @@ static int _start_daemon(char *dmeventd_path, struct dm_event_fifos *fifos)
else if (!pid) {
execvp(args[0], args);
- log_error("Unable to exec dmeventd: %s", strerror(errno));
+ log_error("Unable to exec dmeventd: %s.", strerror(errno));
_exit(EXIT_FAILURE);
} else {
if (waitpid(pid, &status, 0) < 0)
- log_error("Unable to start dmeventd: %s",
+ log_error("Unable to start dmeventd: %s.",
strerror(errno));
else if (WEXITSTATUS(status))
log_error("Unable to start dmeventd.");
@@ -468,10 +504,6 @@ int init_fifos(struct dm_event_fifos *fifos)
/* FIXME? Is fifo the most suitable method? Why not share
comms/daemon code with something else e.g. multipath? */
- /* FIXME Make these either configurable or depend directly on dmeventd_path */
- fifos->client_path = DM_EVENT_FIFO_CLIENT;
- fifos->server_path = DM_EVENT_FIFO_SERVER;
-
/* Open the fifo used to read from the daemon. */
if ((fifos->server = open(fifos->server_path, O_RDWR)) < 0) {
log_sys_error("open", fifos->server_path);
@@ -481,32 +513,27 @@ int init_fifos(struct dm_event_fifos *fifos)
/* Lock out anyone else trying to do communication with the daemon. */
if (flock(fifos->server, LOCK_EX) < 0) {
log_sys_error("flock", fifos->server_path);
- if (close(fifos->server))
- log_sys_error("close", fifos->server_path);
- return 0;
+ goto bad;
}
/* if ((fifos->client = open(fifos->client_path, O_WRONLY | O_NONBLOCK)) < 0) {*/
if ((fifos->client = open(fifos->client_path, O_RDWR | O_NONBLOCK)) < 0) {
log_sys_error("open", fifos->client_path);
- if (close(fifos->server))
- log_sys_error("close", fifos->server_path);
- return 0;
+ goto bad;
}
return 1;
+bad:
+ if (close(fifos->server))
+ log_sys_debug("close", fifos->server_path);
+ fifos->server = -1;
+
+ return 0;
}
/* Initialize client. */
static int _init_client(char *dmeventd_path, struct dm_event_fifos *fifos)
{
- /* init fifos */
- memset(fifos, 0, sizeof(*fifos));
-
- /* FIXME Make these either configurable or depend directly on dmeventd_path */
- fifos->client_path = DM_EVENT_FIFO_CLIENT;
- fifos->server_path = DM_EVENT_FIFO_SERVER;
-
if (!_start_daemon(dmeventd_path, fifos))
return_0;
@@ -515,13 +542,16 @@ static int _init_client(char *dmeventd_path, struct dm_event_fifos *fifos)
void fini_fifos(struct dm_event_fifos *fifos)
{
- if (flock(fifos->server, LOCK_UN))
- log_error("flock unlock %s", fifos->server_path);
+ if (fifos->client >= 0 && close(fifos->client))
+ log_sys_debug("close", fifos->client_path);
- if (close(fifos->client))
- log_sys_error("close", fifos->client_path);
- if (close(fifos->server))
- log_sys_error("close", fifos->server_path);
+ if (fifos->server >= 0) {
+ if (flock(fifos->server, LOCK_UN))
+ log_sys_debug("flock unlock", fifos->server_path);
+
+ if (close(fifos->server))
+ log_sys_debug("close", fifos->server_path);
+ }
}
/* Get uuid of a device */
@@ -531,7 +561,7 @@ static struct dm_task *_get_device_info(const struct dm_event_handler *dmevh)
struct dm_info info;
if (!(dmt = dm_task_create(DM_DEVICE_INFO))) {
- log_error("_get_device_info: dm_task creation for info failed");
+ log_error("_get_device_info: dm_task creation for info failed.");
return NULL;
}
@@ -549,19 +579,19 @@ static struct dm_task *_get_device_info(const struct dm_event_handler *dmevh)
/* FIXME Add name or uuid or devno to messages */
if (!dm_task_run(dmt)) {
- log_error("_get_device_info: dm_task_run() failed");
+ log_error("_get_device_info: dm_task_run() failed.");
goto bad;
}
if (!dm_task_get_info(dmt, &info)) {
- log_error("_get_device_info: failed to get info for device");
+ log_error("_get_device_info: failed to get info for device.");
goto bad;
}
if (!info.exists) {
- log_error("_get_device_info: %s%s%s%.0d%s%.0d%s%s: device not found",
- dmevh->uuid ? : "",
- (!dmevh->uuid && dmevh->dev_name) ? dmevh->dev_name : "",
+ log_error("_get_device_info: %s%s%s%.0d%s%.0d%s%s: device not found.",
+ dmevh->uuid ? : "",
+ (!dmevh->uuid && dmevh->dev_name) ? dmevh->dev_name : "",
(!dmevh->uuid && !dmevh->dev_name && dmevh->major > 0) ? "(" : "",
(!dmevh->uuid && !dmevh->dev_name && dmevh->major > 0) ? dmevh->major : 0,
(!dmevh->uuid && !dmevh->dev_name && dmevh->major > 0) ? ":" : "",
@@ -571,7 +601,6 @@ static struct dm_task *_get_device_info(const struct dm_event_handler *dmevh)
goto bad;
}
-
return dmt;
bad:
@@ -585,21 +614,27 @@ static int _do_event(int cmd, char *dmeventd_path, struct dm_event_daemon_messag
enum dm_event_mask evmask, uint32_t timeout)
{
int ret;
- struct dm_event_fifos fifos;
+ struct dm_event_fifos fifos = {
+ .client = -1,
+ .server = -1,
+ /* FIXME Make these either configurable or depend directly on dmeventd_path */
+ .client_path = DM_EVENT_FIFO_CLIENT,
+ .server_path = DM_EVENT_FIFO_SERVER
+ };
if (!_init_client(dmeventd_path, &fifos)) {
- stack;
- return -ESRCH;
+ ret = -ESRCH;
+ goto_out;
}
ret = daemon_talk(&fifos, msg, DM_EVENT_CMD_HELLO, NULL, NULL, 0, 0);
- dm_free(msg->data);
+ free(msg->data);
msg->data = 0;
if (!ret)
ret = daemon_talk(&fifos, msg, cmd, dso_name, dev_name, evmask, timeout);
-
+out:
/* what is the opposite of init? */
fini_fifos(&fifos);
@@ -612,24 +647,30 @@ int dm_event_register_handler(const struct dm_event_handler *dmevh)
int ret = 1, err;
const char *uuid;
struct dm_task *dmt;
- struct dm_event_daemon_message msg = { 0, 0, NULL };
+ struct dm_event_daemon_message msg = { 0 };
- if (!(dmt = _get_device_info(dmevh))) {
- stack;
- return 0;
- }
+ if (!(dmt = _get_device_info(dmevh)))
+ return_0;
uuid = dm_task_get_uuid(dmt);
+ if (!strstr(dmevh->dso, "libdevmapper-event-lvm2thin.so") &&
+ !strstr(dmevh->dso, "libdevmapper-event-lvm2vdo.so") &&
+ !strstr(dmevh->dso, "libdevmapper-event-lvm2snapshot.so") &&
+ !strstr(dmevh->dso, "libdevmapper-event-lvm2mirror.so") &&
+ !strstr(dmevh->dso, "libdevmapper-event-lvm2raid.so"))
+ log_warn("WARNING: %s: dmeventd plugins are deprecated.", dmevh->dso);
+
+
if ((err = _do_event(DM_EVENT_CMD_REGISTER_FOR_EVENT, dmevh->dmeventd_path, &msg,
dmevh->dso, uuid, dmevh->mask, dmevh->timeout)) < 0) {
- log_error("%s: event registration failed: %s",
+ log_error("%s: event registration failed: %s.",
dm_task_get_name(dmt),
msg.data ? msg.data : strerror(-err));
ret = 0;
}
- dm_free(msg.data);
+ free(msg.data);
dm_task_destroy(dmt);
@@ -641,24 +682,22 @@ int dm_event_unregister_handler(const struct dm_event_handler *dmevh)
int ret = 1, err;
const char *uuid;
struct dm_task *dmt;
- struct dm_event_daemon_message msg = { 0, 0, NULL };
+ struct dm_event_daemon_message msg = { 0 };
- if (!(dmt = _get_device_info(dmevh))) {
- stack;
- return 0;
- }
+ if (!(dmt = _get_device_info(dmevh)))
+ return_0;
uuid = dm_task_get_uuid(dmt);
if ((err = _do_event(DM_EVENT_CMD_UNREGISTER_FOR_EVENT, dmevh->dmeventd_path, &msg,
dmevh->dso, uuid, dmevh->mask, dmevh->timeout)) < 0) {
- log_error("%s: event deregistration failed: %s",
+ log_error("%s: event deregistration failed: %s.",
dm_task_get_name(dmt),
msg.data ? msg.data : strerror(-err));
ret = 0;
}
- dm_free(msg.data);
+ free(msg.data);
dm_task_destroy(dmt);
@@ -670,15 +709,11 @@ int dm_event_unregister_handler(const struct dm_event_handler *dmevh)
static char *_fetch_string(char **src, const int delimiter)
{
char *p, *ret;
+ size_t len = (p = strchr(*src, delimiter)) ?
+ (size_t)(p - *src) : strlen(*src);
- if ((p = strchr(*src, delimiter)))
- *p = 0;
-
- if ((ret = dm_strdup(*src)))
- *src += strlen(ret) + 1;
-
- if (p)
- *p = delimiter;
+ if ((ret = strndup(*src, len)))
+ *src += len + 1;
return ret;
}
@@ -687,20 +722,18 @@ static char *_fetch_string(char **src, const int delimiter)
static int _parse_message(struct dm_event_daemon_message *msg, char **dso_name,
char **uuid, enum dm_event_mask *evmask)
{
- char *id = NULL;
+ char *id;
char *p = msg->data;
if ((id = _fetch_string(&p, ' ')) &&
(*dso_name = _fetch_string(&p, ' ')) &&
(*uuid = _fetch_string(&p, ' '))) {
*evmask = atoi(p);
-
- dm_free(id);
+ free(id);
return 0;
}
- if (id)
- dm_free(id);
+ free(id);
return -ENOMEM;
}
@@ -714,21 +747,24 @@ int dm_event_get_registered_device(struct dm_event_handler *dmevh, int next)
char *reply_dso = NULL, *reply_uuid = NULL;
enum dm_event_mask reply_mask = 0;
struct dm_task *dmt = NULL;
- struct dm_event_daemon_message msg = { 0, 0, NULL };
+ struct dm_event_daemon_message msg = { 0 };
struct dm_info info;
if (!(dmt = _get_device_info(dmevh))) {
- stack;
- return 0;
+ log_debug("Device does not exists (uuid=%s, name=%s, %d:%d).",
+ dmevh->uuid, dmevh->dev_name,
+ dmevh->major, dmevh->minor);
+ ret = -ENODEV;
+ goto fail;
}
uuid = dm_task_get_uuid(dmt);
- if (_do_event(next ? DM_EVENT_CMD_GET_NEXT_REGISTERED_DEVICE :
- DM_EVENT_CMD_GET_REGISTERED_DEVICE, dmevh->dmeventd_path,
- &msg, dmevh->dso, uuid, dmevh->mask, 0)) {
+ /* FIXME Distinguish errors connecting to daemon */
+ if ((ret = _do_event(next ? DM_EVENT_CMD_GET_NEXT_REGISTERED_DEVICE :
+ DM_EVENT_CMD_GET_REGISTERED_DEVICE, dmevh->dmeventd_path,
+ &msg, dmevh->dso, uuid, dmevh->mask, 0))) {
log_debug("%s: device not registered.", dm_task_get_name(dmt));
- ret = -ENOENT;
goto fail;
}
@@ -739,7 +775,7 @@ int dm_event_get_registered_device(struct dm_event_handler *dmevh, int next)
dm_task_destroy(dmt);
dmt = NULL;
- dm_free(msg.data);
+ free(msg.data);
msg.data = NULL;
_dm_event_handler_clear_dev_info(dmevh);
@@ -747,8 +783,8 @@ int dm_event_get_registered_device(struct dm_event_handler *dmevh, int next)
ret = -ENXIO; /* dmeventd probably gave us bogus uuid back */
goto fail;
}
- dmevh->uuid = dm_strdup(reply_uuid);
- if (!dmevh->uuid) {
+
+ if (!(dmevh->uuid = strdup(reply_uuid))) {
ret = -ENOMEM;
goto fail;
}
@@ -761,14 +797,13 @@ int dm_event_get_registered_device(struct dm_event_handler *dmevh, int next)
dm_event_handler_set_dso(dmevh, reply_dso);
dm_event_handler_set_event_mask(dmevh, reply_mask);
- dm_free(reply_dso);
+ free(reply_dso);
reply_dso = NULL;
- dm_free(reply_uuid);
+ free(reply_uuid);
reply_uuid = NULL;
- dmevh->dev_name = dm_strdup(dm_task_get_name(dmt));
- if (!dmevh->dev_name) {
+ if (!(dmevh->dev_name = strdup(dm_task_get_name(dmt)))) {
ret = -ENOMEM;
goto fail;
}
@@ -786,9 +821,9 @@ int dm_event_get_registered_device(struct dm_event_handler *dmevh, int next)
return ret;
fail:
- dm_free(msg.data);
- dm_free(reply_dso);
- dm_free(reply_uuid);
+ free(msg.data);
+ free(reply_dso);
+ free(reply_uuid);
_dm_event_handler_clear_dev_info(dmevh);
if (dmt)
dm_task_destroy(dmt);
@@ -808,23 +843,116 @@ int dm_event_get_registered_device(struct dm_event_handler *dmevh, int next)
int dm_event_get_version(struct dm_event_fifos *fifos, int *version) {
char *p;
- struct dm_event_daemon_message msg = { 0, 0, NULL };
+ struct dm_event_daemon_message msg = { 0 };
if (daemon_talk(fifos, &msg, DM_EVENT_CMD_HELLO, NULL, NULL, 0, 0))
return 0;
p = msg.data;
*version = 0;
- p = strchr(p, ' '); /* Message ID */
- if (!p) return 0;
- p = strchr(p + 1, ' '); /* HELLO */
- if (!p) return 0;
- p = strchr(p + 1, ' '); /* HELLO, once more */
- if (p)
+ if (!p || !(p = strchr(p, ' '))) /* Message ID */
+ return 0;
+ if (!(p = strchr(p + 1, ' '))) /* HELLO */
+ return 0;
+ if ((p = strchr(p + 1, ' '))) /* HELLO, once more */
*version = atoi(p);
+
return 1;
}
+void dm_event_log_set(int debug_log_level, int use_syslog)
+{
+ _debug_level = debug_log_level;
+ _use_syslog = use_syslog;
+}
+
+void dm_event_log(const char *subsys, int level, const char *file,
+ int line, int dm_errno_or_class,
+ const char *format, va_list ap)
+{
+ static int _abort_on_internal_errors = -1;
+ static pthread_mutex_t _log_mutex = PTHREAD_MUTEX_INITIALIZER;
+ static time_t start = 0;
+ const char *indent = "";
+ FILE *stream = log_stderr(level) ? stderr : stdout;
+ int prio;
+ time_t now;
+ int log_with_debug = 0;
+
+ if (subsys[0] == '#') {
+ /* Subsystems starting with '#' are logged
+ * only when debugging is enabled. */
+ log_with_debug++;
+ subsys++;
+ }
+
+ switch (log_level(level)) {
+ case _LOG_DEBUG:
+ /* Never shown without -ddd */
+ if (_debug_level < 3)
+ return;
+ prio = LOG_DEBUG;
+ indent = " ";
+ break;
+ case _LOG_INFO:
+ if (log_with_debug && _debug_level < 2)
+ return;
+ prio = LOG_INFO;
+ indent = " ";
+ break;
+ case _LOG_NOTICE:
+ if (log_with_debug && _debug_level < 1)
+ return;
+ prio = LOG_NOTICE;
+ indent = " ";
+ break;
+ case _LOG_WARN:
+ prio = LOG_WARNING;
+ break;
+ case _LOG_ERR:
+ prio = LOG_ERR;
+ stream = stderr;
+ break;
+ default:
+ prio = LOG_CRIT;
+ }
+
+ /* Serialize to keep lines readable */
+ pthread_mutex_lock(&_log_mutex);
+
+ if (_use_syslog) {
+ vsyslog(prio, format, ap);
+ } else {
+ now = time(NULL);
+ if (!start)
+ start = now;
+ now -= start;
+ if (_debug_level)
+ fprintf(stream, "[%2lld:%02lld] %8x:%-6s%s",
+ (long long)now / 60, (long long)now % 60,
+ // TODO: Maybe use shorter ID
+ // ((int)(pthread_self()) >> 6) & 0xffff,
+ (int)pthread_self(), subsys,
+ (_debug_level > 3) ? "" : indent);
+ if (_debug_level > 3)
+ fprintf(stream, "%28s:%4d %s", file, line, indent);
+ vfprintf(stream, _(format), ap);
+ fputc('\n', stream);
+ fflush(stream);
+ }
+
+ pthread_mutex_unlock(&_log_mutex);
+
+ if (_abort_on_internal_errors < 0)
+ /* Set when env DM_ABORT_ON_INTERNAL_ERRORS is not "0" */
+ _abort_on_internal_errors =
+ strcmp(getenv("DM_ABORT_ON_INTERNAL_ERRORS") ? : "0", "0");
+
+ if (_abort_on_internal_errors &&
+ !strncmp(format, INTERNAL_ERROR, sizeof(INTERNAL_ERROR) - 1))
+ abort();
+}
+
#if 0 /* left out for now */
static char *_skip_string(char *src, const int delimiter)
@@ -837,7 +965,7 @@ static char *_skip_string(char *src, const int delimiter)
int dm_event_set_timeout(const char *device_path, uint32_t timeout)
{
- struct dm_event_daemon_message msg = { 0, 0, NULL };
+ struct dm_event_daemon_message msg = { 0 };
if (!device_exists(device_path))
return -ENODEV;
@@ -849,22 +977,24 @@ int dm_event_set_timeout(const char *device_path, uint32_t timeout)
int dm_event_get_timeout(const char *device_path, uint32_t *timeout)
{
int ret;
- struct dm_event_daemon_message msg = { 0, 0, NULL };
+ struct dm_event_daemon_message msg = { 0 };
if (!device_exists(device_path))
return -ENODEV;
+
if (!(ret = _do_event(DM_EVENT_CMD_GET_TIMEOUT, &msg, NULL, device_path,
0, 0))) {
char *p = _skip_string(msg.data, ' ');
if (!p) {
- log_error("malformed reply from dmeventd '%s'\n",
+ log_error("Malformed reply from dmeventd '%s'.",
msg.data);
+ free(msg.data);
return -EIO;
}
*timeout = atoi(p);
}
- if (msg.data)
- dm_free(msg.data);
+ free(msg.data);
+
return ret;
}
#endif