⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 libdevmapper-event.c

📁 Linux Device Mapper Source Code
💻 C
📖 第 1 页 / 共 2 页
字号:
/* * Copyright (C) 2005-2007 Red Hat, Inc. All rights reserved. * * This file is part of the device-mapper userspace tools. * * This copyrighted material is made available to anyone wishing to use, * modify, copy, or redistribute it subject to the terms and conditions * of the GNU Lesser General Public License v.2.1. * * 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 */#include "lib.h"#include "libdevmapper-event.h"//#include "libmultilog.h"#include "dmeventd.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 */static int _sequence_nr = 0;struct dm_event_handler {	char *dso;	char *dev_name;	char *uuid;	int major;	int minor;	uint32_t timeout;	enum dm_event_mask mask;};static void _dm_event_handler_clear_dev_info(struct dm_event_handler *dmevh){	if (dmevh->dev_name)		dm_free(dmevh->dev_name);	if (dmevh->uuid)		dm_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;	if (!(dmevh = dm_malloc(sizeof(*dmevh))))		return NULL;	dmevh->dso = dmevh->dev_name = dmevh->uuid = NULL;	dmevh->major = dmevh->minor = 0;	dmevh->mask = 0;	dmevh->timeout = 0;	return dmevh;}void dm_event_handler_destroy(struct dm_event_handler *dmevh){	_dm_event_handler_clear_dev_info(dmevh);	if (dmevh->dso)		dm_free(dmevh->dso);	dm_free(dmevh);}int dm_event_handler_set_dso(struct dm_event_handler *dmevh, const char *path){	if (!path) /* noop */		return 0;	if (dmevh->dso)		dm_free(dmevh->dso);	dmevh->dso = dm_strdup(path);	if (!dmevh->dso)		return -ENOMEM;	return 0;}int dm_event_handler_set_dev_name(struct dm_event_handler *dmevh, const char *dev_name){	if (!dev_name)		return 0;	_dm_event_handler_clear_dev_info(dmevh);	dmevh->dev_name = dm_strdup(dev_name);	if (!dmevh->dev_name)		return -ENOMEM;	return 0;}int dm_event_handler_set_uuid(struct dm_event_handler *dmevh, const char *uuid){	if (!uuid)		return 0;	_dm_event_handler_clear_dev_info(dmevh);	dmevh->uuid = dm_strdup(uuid);	if (!dmevh->dev_name)		return -ENOMEM;	return 0;}void dm_event_handler_set_major(struct dm_event_handler *dmevh, int major){	int minor = dmevh->minor;	_dm_event_handler_clear_dev_info(dmevh);	dmevh->major = major;	dmevh->minor = minor;}void dm_event_handler_set_minor(struct dm_event_handler *dmevh, int minor){	int major = dmevh->major;	_dm_event_handler_clear_dev_info(dmevh);	dmevh->major = major;	dmevh->minor = minor;}void dm_event_handler_set_event_mask(struct dm_event_handler *dmevh,				     enum dm_event_mask evmask){	dmevh->mask = evmask;}void dm_event_handler_set_timeout(struct dm_event_handler *dmevh, int timeout){	dmevh->timeout = timeout;}const char *dm_event_handler_get_dso(const struct dm_event_handler *dmevh){	return dmevh->dso;}const char *dm_event_handler_get_dev_name(const struct dm_event_handler *dmevh){	return dmevh->dev_name;}const char *dm_event_handler_get_uuid(const struct dm_event_handler *dmevh){	return dmevh->uuid;}int dm_event_handler_get_major(const struct dm_event_handler *dmevh){	return dmevh->major;}int dm_event_handler_get_minor(const struct dm_event_handler *dmevh){	return dmevh->minor;}int dm_event_handler_get_timeout(const struct dm_event_handler *dmevh){	return dmevh->timeout;}enum dm_event_mask dm_event_handler_get_event_mask(const struct dm_event_handler *dmevh){	return dmevh->mask;}static int _check_message_id(struct dm_event_daemon_message *msg){	int pid, seq_nr;	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(),			  _sequence_nr, msg->data);		return 0;	}	return 1;}/* * daemon_read * @fifos * @msg * * Read message from daemon. * * Returns: 0 on failure, 1 on success */static int _daemon_read(struct dm_event_fifos *fifos,			struct dm_event_daemon_message *msg){	unsigned bytes = 0;	int ret, i;	fd_set fds;	struct timeval tval = { 0, 0 };	size_t size = 2 * sizeof(uint32_t);	/* status + size */	char *buf = alloca(size);	int header = 1;	while (bytes < size) {		for (i = 0, ret = 0; (i < 20) && (ret < 1); i++) {			/* Watch daemon read FIFO for input. */			FD_ZERO(&fds);			FD_SET(fifos->server, &fds);			tval.tv_sec = 1;			ret = select(fifos->server + 1, &fds, NULL, NULL,				     &tval);			if (ret < 0 && errno != EINTR) {				log_error("Unable to read from event server");				return 0;			}		}		if (ret < 1) {			log_error("Unable to read from event server.");			return 0;		}		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;			}		}		bytes += ret;		if (bytes == 2 * sizeof(uint32_t) && header) {			msg->cmd = ntohl(*((uint32_t *)buf));			msg->size = ntohl(*((uint32_t *)buf + 1));			buf = msg->data = dm_malloc(msg->size);			size = msg->size;			bytes = 0;			header = 0;		}	}	if (bytes != size) {		if (msg->data)			dm_free(msg->data);		msg->data = NULL;	}	return bytes == size;}/* 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;	fd_set fds;	size_t size = 2 * sizeof(uint32_t) + msg->size;	char *buf = alloca(size);	char drainbuf[128];	struct timeval tval = { 0, 0 };	*((uint32_t *)buf) = htonl(msg->cmd);	*((uint32_t *)buf + 1) = htonl(msg->size);	memcpy(buf + 2 * sizeof(uint32_t), msg->data, msg->size);	/* drain the answer fifo */	while (1) {		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");			return 0;		}		if (ret == 0)			break;		read(fifos->server, drainbuf, 127);	}	while (bytes < size) {		do {			/* Watch daemon write FIFO to be ready for output. */			FD_ZERO(&fds);			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");				return 0;			}		} while (ret < 1);		ret = write(fifos->client, ((char *) buf) + bytes,			    size - bytes);		if (ret < 0) {			if ((errno == EINTR) || (errno == EAGAIN))				continue;			else {				log_error("Unable to talk to event daemon");				return 0;			}		}		bytes += ret;	}	return bytes == size;}static int _daemon_talk(struct dm_event_fifos *fifos,			struct dm_event_daemon_message *msg, int cmd,			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));	/*	 * 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");		return -ENOMEM;	}	msg->size = msg_size;	/*	 * Write command and message to and	 * read status return code from daemon.	 */	if (!_daemon_write(fifos, msg)) {		stack;		dm_free(msg->data);		msg->data = 0;		return -EIO;	}	do {		if (msg->data)			dm_free(msg->data);		msg->data = 0;		if (!_daemon_read(fifos, msg)) {			stack;			return -EIO;		}	} while (!_check_message_id(msg));	_sequence_nr++;	return (int32_t) msg->cmd;}/* * start_daemon * * This function forks off a process (dmeventd) that will handle * the events.  I am currently test opening one of the fifos to * ensure that the daemon is running and listening...  I thought * this would be less expensive than fork/exec'ing every time. * Perhaps there is an even quicker/better way (no, checking the * lock file is _not_ a better way). * * Returns: 1 on success, 0 otherwise */static int _start_daemon(struct dm_event_fifos *fifos){	int pid, ret = 0;	int status;	struct stat statbuf;	if (stat(fifos->client_path, &statbuf))		goto start_server;

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -