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

📄 libdevmapper-event.c

📁 Linux Device Mapper Source Code
💻 C
📖 第 1 页 / 共 2 页
字号:
	if (!S_ISFIFO(statbuf.st_mode)) {		log_error("%s is not a fifo.", 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) {		/* server is running and listening */		close(fifos->client);		return 1;	} else if (errno != ENXIO) {		/* problem */		log_error("%s: Can't open client fifo %s: %s",			  __func__, fifos->client_path, strerror(errno));		stack;		return 0;	}      start_server:	/* server is not running */	pid = fork();	if (pid < 0)		log_error("Unable to fork.");	else if (!pid) {		execvp(DMEVENTD_PATH, NULL);		exit(EXIT_FAILURE);	} else {		if (waitpid(pid, &status, 0) < 0)			log_error("Unable to start dmeventd: %s",				  strerror(errno));		else if (WEXITSTATUS(status))			log_error("Unable to start dmeventd.");		else			ret = 1;	}	return ret;}/* Initialize client. */static int _init_client(struct dm_event_fifos *fifos){	/* FIXME? Is fifo the most suitable method? Why not share	   comms/daemon code with something else e.g. multipath? */	/* init fifos */	memset(fifos, 0, sizeof(*fifos));	fifos->client_path = DM_EVENT_FIFO_CLIENT;	fifos->server_path = DM_EVENT_FIFO_SERVER;	if (!_start_daemon(fifos)) {		stack;		return 0;	}	/* Open the fifo used to read from the daemon. */	if ((fifos->server = open(fifos->server_path, O_RDWR)) < 0) {		log_error("%s: open server fifo %s",			  __func__, fifos->server_path);		stack;		return 0;	}	/* Lock out anyone else trying to do communication with the daemon. */	if (flock(fifos->server, LOCK_EX) < 0) {		log_error("%s: flock %s", __func__, fifos->server_path);		close(fifos->server);		return 0;	}/*	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_error("%s: Can't open client fifo %s: %s",			  __func__, fifos->client_path, strerror(errno));		close(fifos->server);		stack;		return 0;	}	return 1;}static void _dtr_client(struct dm_event_fifos *fifos){	if (flock(fifos->server, LOCK_UN))		log_error("flock unlock %s", fifos->server_path);	close(fifos->client);	close(fifos->server);}/* Get uuid of a device */static struct dm_task *_get_device_info(const struct dm_event_handler *dmevh){	struct dm_task *dmt;	struct dm_info info;	if (!(dmt = dm_task_create(DM_DEVICE_INFO))) {		log_error("_get_device_info: dm_task creation for info failed");		return NULL;	}	if (dmevh->uuid)		dm_task_set_uuid(dmt, dmevh->uuid);	else if (dmevh->dev_name)		dm_task_set_name(dmt, dmevh->dev_name);	else if (dmevh->major && dmevh->minor) {		dm_task_set_major(dmt, dmevh->major);		dm_task_set_minor(dmt, dmevh->minor);        }	/* FIXME Add name or uuid or devno to messages */	if (!dm_task_run(dmt)) {		log_error("_get_device_info: dm_task_run() failed");		goto failed;	}	if (!dm_task_get_info(dmt, &info)) {		log_error("_get_device_info: failed to get info for device");		goto failed;	}	if (!info.exists) {		log_error("_get_device_info: device not found");		goto failed;	}	return dmt;failed:	dm_task_destroy(dmt);	return NULL;}/* Handle the event (de)registration call and return negative error codes. */static int _do_event(int cmd, struct dm_event_daemon_message *msg,		     const char *dso_name, const char *dev_name,		     enum dm_event_mask evmask, uint32_t timeout){	int ret;	struct dm_event_fifos fifos;	if (!_init_client(&fifos)) {		stack;		return -ESRCH;	}	ret = _daemon_talk(&fifos, msg, DM_EVENT_CMD_HELLO, 0, 0, 0, 0);	if (msg->data)		dm_free(msg->data);	msg->data = 0;	if (!ret)		ret = _daemon_talk(&fifos, msg, cmd, dso_name, dev_name, evmask, timeout);	/* what is the opposite of init? */	_dtr_client(&fifos);	return ret;}/* External library interface. */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 };	if (!(dmt = _get_device_info(dmevh))) {		stack;		return 0;	}	uuid = dm_task_get_uuid(dmt);	if ((err = _do_event(DM_EVENT_CMD_REGISTER_FOR_EVENT, &msg,			     dmevh->dso, uuid, dmevh->mask, dmevh->timeout)) < 0) {		log_error("%s: event registration failed: %s",			  dm_task_get_name(dmt),			  msg.data ? msg.data : strerror(-err));		ret = 0;	}	if (msg.data)		dm_free(msg.data);	dm_task_destroy(dmt);	return ret;}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 };	if (!(dmt = _get_device_info(dmevh))) {		stack;		return 0;	}	uuid = dm_task_get_uuid(dmt);	if ((err = _do_event(DM_EVENT_CMD_UNREGISTER_FOR_EVENT, &msg,			    dmevh->dso, uuid, dmevh->mask, dmevh->timeout)) < 0) {		log_error("%s: event deregistration failed: %s",			  dm_task_get_name(dmt),			  msg.data ? msg.data : strerror(-err));		ret = 0;	}	if (msg.data)		dm_free(msg.data);	dm_task_destroy(dmt);	return ret;}/* Fetch a string off src and duplicate it into *dest. *//* FIXME: move to separate module to share with the daemon. */static char *_fetch_string(char **src, const int delimiter){	char *p, *ret;	if ((p = strchr(*src, delimiter)))		*p = 0;	if ((ret = dm_strdup(*src)))		*src += strlen(ret) + 1;	if (p)		*p = delimiter;	return ret;}/* Parse a device message from the daemon. */static int _parse_message(struct dm_event_daemon_message *msg, char **dso_name,			 char **uuid, enum dm_event_mask *evmask){	char *id = NULL;	char *p = msg->data;	if ((id = _fetch_string(&p, ' ')) &&	    (*dso_name = _fetch_string(&p, ' ')) &&	    (*uuid = _fetch_string(&p, ' '))) {		*evmask = atoi(p);		dm_free(id);		return 0;	}	if (id)		dm_free(id);	return -ENOMEM;}/* * Returns 0 if handler found; error (-ENOMEM, -ENOENT) otherwise. */int dm_event_get_registered_device(struct dm_event_handler *dmevh, int next){	int ret = 0;	const char *uuid = NULL;	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 };	if (!(dmt = _get_device_info(dmevh))) {		stack;		return 0;	}	uuid = dm_task_get_uuid(dmt);	if (!(ret = _do_event(next ? DM_EVENT_CMD_GET_NEXT_REGISTERED_DEVICE :			     DM_EVENT_CMD_GET_REGISTERED_DEVICE,			      &msg, dmevh->dso, uuid, dmevh->mask, 0))) {		/* FIXME this will probably horribly break if we get		   ill-formatted reply */		ret = _parse_message(&msg, &reply_dso, &reply_uuid, &reply_mask);	} else {		ret = -ENOENT;		goto fail;	}	dm_task_destroy(dmt);	dmt = NULL;	if (msg.data) {		dm_free(msg.data);		msg.data = NULL;	}	_dm_event_handler_clear_dev_info(dmevh);	dmevh->uuid = dm_strdup(reply_uuid);	if (!dmevh->uuid) {		ret = -ENOMEM;		goto fail;	}	if (!(dmt = _get_device_info(dmevh))) {		ret = -ENXIO; /* dmeventd probably gave us bogus uuid back */		goto fail;	}	dm_event_handler_set_dso(dmevh, reply_dso);	dm_event_handler_set_event_mask(dmevh, reply_mask);	if (reply_dso)		dm_free(reply_dso);	if (reply_uuid)		dm_free(reply_uuid);	dmevh->dev_name = dm_strdup(dm_task_get_name(dmt));	if (!dmevh->dev_name) {		ret = -ENOMEM;		goto fail;	}	struct dm_info info;	if (!dm_task_get_info(dmt, &info)) {		ret = -1;		goto fail;	}	dmevh->major = info.major;	dmevh->minor = info.minor;	dm_task_destroy(dmt);	return ret; fail:	if (msg.data)		dm_free(msg.data);	if (reply_dso)		dm_free(reply_dso);	if (reply_uuid)		dm_free(reply_uuid);	_dm_event_handler_clear_dev_info(dmevh);	if (dmt)		dm_task_destroy(dmt);	return ret;}#if 0				/* left out for now */static char *_skip_string(char *src, const int delimiter){	src = srtchr(src, delimiter);	if (src && *(src + 1))		return src + 1;	return NULL;}int dm_event_set_timeout(const char *device_path, uint32_t timeout){	struct dm_event_daemon_message msg = { 0, 0, NULL };	if (!device_exists(device_path))		return -ENODEV;	return _do_event(DM_EVENT_CMD_SET_TIMEOUT, &msg,			 NULL, device_path, 0, timeout);}int dm_event_get_timeout(const char *device_path, uint32_t *timeout){	int ret;	struct dm_event_daemon_message msg = { 0, 0, NULL };	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",				  msg.data);			return -EIO;		}		*timeout = atoi(p);	}	if (msg.data)		dm_free(msg.data);	return ret;}#endif

⌨️ 快捷键说明

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