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

📄 libdm-iface.c

📁 Linux Device Mapper Source Code
💻 C
📖 第 1 页 / 共 3 页
字号:
      bad:	dm_free(dmi);	return NULL;}static int _dm_names_v1(struct dm_ioctl_v1 *dmi){	const char *dev_dir = dm_dir();	int r = 1, len;	const char *name;	struct dirent *dirent;	DIR *d;	struct dm_names *names, *old_names = NULL;	void *end = (void *) dmi + dmi->data_size;	struct stat buf;	char path[PATH_MAX];	log_warn("WARNING: Device list may be incomplete with interface "		  "version 1.");	log_warn("Please upgrade your kernel device-mapper driver.");	if (!(d = opendir(dev_dir))) {		log_sys_error("opendir", dev_dir);		return 0;	}	names = (struct dm_names *) ((void *) dmi + dmi->data_start);	names->dev = 0;		/* Flags no data */	while ((dirent = readdir(d))) {		name = dirent->d_name;		if (name[0] == '.' || !strcmp(name, "control"))			continue;		if (old_names)			old_names->next = (uint32_t) ((void *) names -						      (void *) old_names);		snprintf(path, sizeof(path), "%s/%s", dev_dir, name);		if (stat(path, &buf)) {			log_sys_error("stat", path);			continue;		}		if (!S_ISBLK(buf.st_mode))			continue;		names->dev = (uint64_t) buf.st_rdev;		names->next = 0;		len = strlen(name);		if (((void *) (names + 1) + len + 1) >= end) {			log_error("Insufficient buffer space for device list");			r = 0;			break;		}		strcpy(names->name, name);		old_names = names;		names = _align((void *) ++names + len + 1, ALIGNMENT);	}	if (closedir(d))		log_sys_error("closedir", dev_dir);	return r;}static int _dm_task_run_v1(struct dm_task *dmt){	struct dm_ioctl_v1 *dmi;	unsigned int command;	dmi = _flatten_v1(dmt);	if (!dmi) {		log_error("Couldn't create ioctl argument.");		return 0;	}	if (!_open_control())		return 0;	if ((unsigned) dmt->type >=	    (sizeof(_cmd_data_v1) / sizeof(*_cmd_data_v1))) {		log_error("Internal error: unknown device-mapper task %d",			  dmt->type);		goto bad;	}	command = _cmd_data_v1[dmt->type].cmd;	if (dmt->type == DM_DEVICE_TABLE)		dmi->flags |= DM_STATUS_TABLE_FLAG;	log_debug("dm %s %s %s%s%s [%u]", _cmd_data_v1[dmt->type].name,		  dmi->name, dmi->uuid, dmt->newname ? " " : "",		  dmt->newname ? dmt->newname : "",		  dmi->data_size);	if (dmt->type == DM_DEVICE_LIST) {		if (!_dm_names_v1(dmi))			goto bad;	} #ifdef DM_IOCTLS	else if (ioctl(_control_fd, command, dmi) < 0) {		if (_log_suppress)			log_verbose("device-mapper: %s ioctl failed: %s", 				    _cmd_data_v1[dmt->type].name,				    strerror(errno));		else			log_error("device-mapper: %s ioctl failed: %s",				  _cmd_data_v1[dmt->type].name,				  strerror(errno));		goto bad;	}#else /* Userspace alternative for testing */#endif	if (dmi->flags & DM_BUFFER_FULL_FLAG)		/* FIXME Increase buffer size and retry operation (if query) */		log_error("WARNING: libdevmapper buffer too small for data");	switch (dmt->type) {	case DM_DEVICE_CREATE:		add_dev_node(dmt->dev_name, MAJOR(dmi->dev), MINOR(dmi->dev),			     dmt->uid, dmt->gid, dmt->mode);		break;	case DM_DEVICE_REMOVE:		rm_dev_node(dmt->dev_name);		break;	case DM_DEVICE_RENAME:		rename_dev_node(dmt->dev_name, dmt->newname);		break;	case DM_DEVICE_MKNODES:		if (dmi->flags & DM_EXISTS_FLAG)			add_dev_node(dmt->dev_name, MAJOR(dmi->dev),				     MINOR(dmi->dev),				     dmt->uid, dmt->gid, dmt->mode);		else			rm_dev_node(dmt->dev_name);		break;	case DM_DEVICE_STATUS:	case DM_DEVICE_TABLE:		if (!_unmarshal_status_v1(dmt, dmi))			goto bad;		break;	case DM_DEVICE_SUSPEND:	case DM_DEVICE_RESUME:		dmt->type = DM_DEVICE_INFO;		if (!dm_task_run(dmt))			goto bad;		dm_free(dmi);	/* We'll use what info returned */		return 1;	}	dmt->dmi.v1 = dmi;	return 1;      bad:	dm_free(dmi);	return 0;}#endif/* * Protocol Version 4 functions. */int dm_task_get_driver_version(struct dm_task *dmt, char *version, size_t size){	unsigned *v;#ifdef DM_COMPAT	if (_dm_version == 1)		return _dm_task_get_driver_version_v1(dmt, version, size);#endif	if (!dmt->dmi.v4) {		version[0] = '\0';		return 0;	}	v = dmt->dmi.v4->version;	snprintf(version, size, "%u.%u.%u", v[0], v[1], v[2]);	_dm_version_minor = v[1];	_dm_version_patchlevel = v[2];	return 1;}static int _check_version(char *version, size_t size, int log_suppress){	struct dm_task *task;	int r;	if (!(task = dm_task_create(DM_DEVICE_VERSION))) {		log_error("Failed to get device-mapper version");		version[0] = '\0';		return 0;	}	if (log_suppress)		_log_suppress = 1;	r = dm_task_run(task);	dm_task_get_driver_version(task, version, size);	dm_task_destroy(task);	_log_suppress = 0;	return r;}/* * Find out device-mapper's major version number the first time  * this is called and whether or not we support it. */int dm_check_version(void){	char libversion[64], dmversion[64];	const char *compat = "";	if (_version_checked)		return _version_ok;	_version_checked = 1;	if (_check_version(dmversion, sizeof(dmversion), _dm_compat))		return 1;	if (!_dm_compat)		goto bad;	log_verbose("device-mapper ioctl protocol version %u failed. "		    "Trying protocol version 1.", _dm_version);	_dm_version = 1;	if (_check_version(dmversion, sizeof(dmversion), 0)) {		log_verbose("Using device-mapper ioctl protocol version 1");		return 1;	}	compat = "(compat)";	dm_get_library_version(libversion, sizeof(libversion));	log_error("Incompatible libdevmapper %s%s and kernel driver %s",		  libversion, compat, dmversion);      bad:	_version_ok = 0;	return 0;}void *dm_get_next_target(struct dm_task *dmt, void *next,			 uint64_t *start, uint64_t *length,			 char **target_type, char **params){	struct target *t = (struct target *) next;	if (!t)		t = dmt->head;	if (!t)		return NULL;	*start = t->start;	*length = t->length;	*target_type = t->type;	*params = t->params;	return t->next;}/* Unmarshall the target info returned from a status call */static int _unmarshal_status(struct dm_task *dmt, struct dm_ioctl *dmi){	char *outbuf = (char *) dmi + dmi->data_start;	char *outptr = outbuf;	uint32_t i;	struct dm_target_spec *spec;	for (i = 0; i < dmi->target_count; i++) {		spec = (struct dm_target_spec *) outptr;		if (!dm_task_add_target(dmt, spec->sector_start,					spec->length,					spec->target_type,					outptr + sizeof(*spec))) {			return 0;		}		outptr = outbuf + spec->next;	}	return 1;}int dm_format_dev(char *buf, int bufsize, uint32_t dev_major,		  uint32_t dev_minor){	int r;#ifdef DM_COMPAT	if (_dm_version == 1)		return _dm_format_dev_v1(buf, bufsize, dev_major, dev_minor);#endif	if (bufsize < 8)		return 0;	r = snprintf(buf, (size_t) bufsize, "%u:%u", dev_major, dev_minor);	if (r < 0 || r > bufsize - 1)		return 0;	return 1;}int dm_task_get_info(struct dm_task *dmt, struct dm_info *info){#ifdef DM_COMPAT	if (_dm_version == 1)		return _dm_task_get_info_v1(dmt, info);#endif	if (!dmt->dmi.v4)		return 0;	memset(info, 0, sizeof(*info));	info->exists = dmt->dmi.v4->flags & DM_EXISTS_FLAG ? 1 : 0;	if (!info->exists)		return 1;	info->suspended = dmt->dmi.v4->flags & DM_SUSPEND_FLAG ? 1 : 0;	info->read_only = dmt->dmi.v4->flags & DM_READONLY_FLAG ? 1 : 0;	info->live_table = dmt->dmi.v4->flags & DM_ACTIVE_PRESENT_FLAG ? 1 : 0;	info->inactive_table = dmt->dmi.v4->flags & DM_INACTIVE_PRESENT_FLAG ?	    1 : 0;	info->target_count = dmt->dmi.v4->target_count;	info->open_count = dmt->dmi.v4->open_count;	info->event_nr = dmt->dmi.v4->event_nr;	info->major = MAJOR(dmt->dmi.v4->dev);	info->minor = MINOR(dmt->dmi.v4->dev);	return 1;}const char *dm_task_get_name(const struct dm_task *dmt){#ifdef DM_COMPAT	if (_dm_version == 1)		return _dm_task_get_name_v1(dmt);#endif	return (dmt->dmi.v4->name);}const char *dm_task_get_uuid(const struct dm_task *dmt){#ifdef DM_COMPAT	if (_dm_version == 1)		return _dm_task_get_uuid_v1(dmt);#endif	return (dmt->dmi.v4->uuid);}struct dm_deps *dm_task_get_deps(struct dm_task *dmt){#ifdef DM_COMPAT	if (_dm_version == 1)		return _dm_task_get_deps_v1(dmt);#endif	return (struct dm_deps *) (((void *) dmt->dmi.v4) +				   dmt->dmi.v4->data_start);}struct dm_names *dm_task_get_names(struct dm_task *dmt){#ifdef DM_COMPAT	if (_dm_version == 1)		return _dm_task_get_names_v1(dmt);#endif	return (struct dm_names *) (((void *) dmt->dmi.v4) +				    dmt->dmi.v4->data_start);}struct dm_versions *dm_task_get_versions(struct dm_task *dmt){	return (struct dm_versions *) (((void *) dmt->dmi.v4) +				       dmt->dmi.v4->data_start);}int dm_task_set_ro(struct dm_task *dmt){	dmt->read_only = 1;	return 1;}int dm_task_suppress_identical_reload(struct dm_task *dmt){	dmt->suppress_identical_reload = 1;	return 1;}int dm_task_set_newname(struct dm_task *dmt, const char *newname){	if (!(dmt->newname = dm_strdup(newname))) {		log_error("dm_task_set_newname: strdup(%s) failed", newname);		return 0;	}	return 1;}int dm_task_set_message(struct dm_task *dmt, const char *message){	if (!(dmt->message = dm_strdup(message))) {		log_error("dm_task_set_message: strdup(%s) failed", message);		return 0;	}	return 1;}int dm_task_set_sector(struct dm_task *dmt, uint64_t sector){	dmt->sector = sector;	return 1;}int dm_task_set_geometry(struct dm_task *dmt, const char *cylinders, const char *heads, const char *sectors, const char *start){	size_t len = strlen(cylinders) + 1 + strlen(heads) + 1 + strlen(sectors) + 1 + strlen(start) + 1;	if (!(dmt->geometry = dm_malloc(len))) {		log_error("dm_task_set_geometry: dm_malloc failed");		return 0;	}	if (sprintf(dmt->geometry, "%s %s %s %s", cylinders, heads, sectors, start) < 0) {		log_error("dm_task_set_geometry: sprintf failed");		return 0;	}	return 1;}int dm_task_no_flush(struct dm_task *dmt){	dmt->no_flush = 1;	return 1;}int dm_task_no_open_count(struct dm_task *dmt){	dmt->no_open_count = 1;	return 1;}int dm_task_skip_lockfs(struct dm_task *dmt){	dmt->skip_lockfs = 1;	return 1;}int dm_task_set_event_nr(struct dm_task *dmt, uint32_t event_nr){	dmt->event_nr = event_nr;	return 1;}struct target *create_target(uint64_t start, uint64_t len, const char *type,			     const char *params){	struct target *t = dm_malloc(sizeof(*t));	if (!t) {		log_error("create_target: malloc(%" PRIsize_t ") failed",			  sizeof(*t));		return NULL;	}	memset(t, 0, sizeof(*t));	if (!(t->params = dm_strdup(params))) {		log_error("create_target: strdup(params) failed");		goto bad;	}	if (!(t->type = dm_strdup(type))) {		log_error("create_target: strdup(type) failed");		goto bad;	}	t->start = start;	t->length = len;	return t;      bad:	dm_free(t->params);	dm_free(t->type);	dm_free(t);	return NULL;}static void *_add_target(struct target *t, void *out, void *end){	void *out_sp = out;	struct dm_target_spec sp;	size_t sp_size = sizeof(struct dm_target_spec);	int len;	const char no_space[] = "Ran out of memory building ioctl parameter";	out += sp_size;	if (out >= end) {		log_error(no_space);		return NULL;	}	sp.status = 0;	sp.sector_start = t->start;	sp.length = t->length;	strncpy(sp.target_type, t->type, sizeof(sp.target_type));	len = strlen(t->params);	if ((out + len + 1) >= end) {		log_error(no_space);		log_error("t->params= '%s'", t->params);		return NULL;	}	strcpy((char *) out, t->params);	out += len + 1;	/* align next block */	out = _align(out, ALIGNMENT);	sp.next = out - out_sp;	memcpy(out_sp, &sp, sp_size);	return out;}static int _lookup_dev_name(uint64_t dev, char *buf, size_t len){	struct dm_names *names;	unsigned next = 0;	struct dm_task *dmt;	int r = 0; 	if (!(dmt = dm_task_create(DM_DEVICE_LIST)))		return 0; 	if (!dm_task_run(dmt))		goto out;	if (!(names = dm_task_get_names(dmt)))		goto out; 	if (!names->dev)		goto out; 

⌨️ 快捷键说明

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