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

📄 dmsetup.c

📁 Linux Device Mapper Source Code
💻 C
📖 第 1 页 / 共 4 页
字号:
static void _out_char(const unsigned c){	/* Only first UTF-8 char counts */	_cur_x += ((c & 0xc0) != 0x80);	if (!_tree_switches[TR_TRUNCATE]) {		putchar((int) c);		return;	}	/* Truncation? */	if (_cur_x <= _termwidth)		putchar((int) c);	if (_cur_x == _termwidth + 1 && ((c & 0xc0) != 0x80)) {		if (_last_char || (c & 0x80)) {			putchar('.');			putchar('.');			putchar('.');		} else {			_last_char = c;			_cur_x--;		}	}}static void _out_string(const char *str){	while (*str)		_out_char((unsigned char) *str++);}/* non-negative integers only */static unsigned _out_int(unsigned num){	unsigned digits = 0;	unsigned divi;	if (!num) {		_out_char('0');		return 1;	}	/* non zero case */	for (divi = 1; num / divi; divi *= 10)		digits++;	for (divi /= 10; divi; divi /= 10)		_out_char('0' + (num / divi) % 10);	return digits;}static void _out_newline(void){	if (_last_char && _cur_x == _termwidth)		putchar(_last_char);	_last_char = 0;	putchar('\n');	_cur_x = 1;}static void _out_prefix(unsigned depth){	unsigned x, d;	for (d = 0; d < depth; d++) {		for (x = _tree_width[d] + 1; x > 0; x--)			_out_char(' ');		_out_string(d == depth - 1 ?				!_tree_more[depth] ? _tsym->last_2 : _tsym->branch_2			   : _tree_more[d + 1] ?				_tsym->vert_2 : _tsym->empty_2);	}}/* * Display tree */static void _display_tree_attributes(struct dm_tree_node *node){	int attr = 0;	const char *uuid;	const struct dm_info *info;	uuid = dm_tree_node_get_uuid(node);	info = dm_tree_node_get_info(node);	if (!info->exists)		return;	if (_tree_switches[TR_ACTIVE]) {		_out_string(attr++ ? ", " : " [");		_out_string(info->suspended ? "SUSPENDED" : "ACTIVE");	}	if (_tree_switches[TR_RW]) {		_out_string(attr++ ? ", " : " [");		_out_string(info->read_only ? "RO" : "RW");	}	if (_tree_switches[TR_OPENCOUNT]) {		_out_string(attr++ ? ", " : " [");		(void) _out_int((unsigned) info->open_count);	}	if (_tree_switches[TR_UUID]) {		_out_string(attr++ ? ", " : " [");		_out_string(uuid && *uuid ? uuid : "");	}	if (attr)		_out_char(']');}static void _display_tree_node(struct dm_tree_node *node, unsigned depth,			       unsigned first_child __attribute((unused)),			       unsigned last_child, unsigned has_children){	int offset;	const char *name;	const struct dm_info *info;	int first_on_line = 0;	/* Sub-tree for targets has 2 more depth */	if (depth + 2 > MAX_DEPTH)		return;	name = dm_tree_node_get_name(node);	if ((!name || !*name) && !_tree_switches[TR_DEVICE])		return;	/* Indicate whether there are more nodes at this depth */	_tree_more[depth] = !last_child;	_tree_width[depth] = 0;	if (_cur_x == 1)		first_on_line = 1;	if (!TR_PRINT_COMPACT || first_on_line)		_out_prefix(depth);	/* Remember the starting point for compact */	offset = _cur_x;	if (TR_PRINT_COMPACT && !first_on_line)		_out_string(_tree_more[depth] ? _tsym->first_3 : _tsym->single_3);	/* display node */	if (name)		_out_string(name);	info = dm_tree_node_get_info(node);	if (_tree_switches[TR_DEVICE]) {		_out_string(name ? " (" : "(");		(void) _out_int(info->major);		_out_char(':');		(void) _out_int(info->minor);		_out_char(')');	}	/* display additional info */	if (TR_PRINT_ATTRIBUTE)		_display_tree_attributes(node);	if (TR_PRINT_COMPACT)		_tree_width[depth] = _cur_x - offset;	if (!TR_PRINT_COMPACT || !has_children)		_out_newline();	if (TR_PRINT_TARGETS) {		_tree_more[depth + 1] = has_children;		// FIXME _display_tree_targets(name, depth + 2);	}}/* * Walk the dependency tree */static void _display_tree_walk_children(struct dm_tree_node *node,					unsigned depth){	struct dm_tree_node *child, *next_child;	void *handle = NULL;	uint32_t inverted = _tree_switches[TR_BOTTOMUP];	unsigned first_child = 1;	unsigned has_children;	next_child = dm_tree_next_child(&handle, node, inverted);	while ((child = next_child)) {		next_child = dm_tree_next_child(&handle, node, inverted);		has_children =		    dm_tree_node_num_children(child, inverted) ? 1 : 0;		_display_tree_node(child, depth, first_child,				   next_child ? 0U : 1U, has_children);		if (has_children)			_display_tree_walk_children(child, depth + 1);		first_child = 0;	}}static int _add_dep(int argc __attribute((unused)), char **argv __attribute((unused)), void *data){	struct dm_names *names = (struct dm_names *) data;	if (!dm_tree_add_dev(_dtree, (unsigned) MAJOR(names->dev), (unsigned) MINOR(names->dev)))		return 0;	return 1;}/* * Create and walk dependency tree */static int _build_whole_deptree(void){	if (_dtree)		return 1;	if (!(_dtree = dm_tree_create()))		return 0;	if (!_process_all(0, NULL, 0, _add_dep))		return 0;	return 1;}static int _display_tree(int argc __attribute((unused)),			 char **argv __attribute((unused)),			 void *data __attribute((unused))){	if (!_build_whole_deptree())		return 0;	_display_tree_walk_children(dm_tree_find_node(_dtree, 0, 0), 0);	return 1;}/* * Report device information *//* dm specific display functions */static int _int32_disp(struct dm_report *rh,		       struct dm_pool *mem __attribute((unused)),		       struct dm_report_field *field, const void *data,		       void *private __attribute((unused))){	const int32_t value = *(const int32_t *)data;	return dm_report_field_int32(rh, field, &value);}static int _uint32_disp(struct dm_report *rh,			struct dm_pool *mem __attribute((unused)),			struct dm_report_field *field, const void *data,			void *private __attribute((unused))){	const uint32_t value = *(const int32_t *)data;	return dm_report_field_uint32(rh, field, &value);}static int _dm_name_disp(struct dm_report *rh,			 struct dm_pool *mem __attribute((unused)),			 struct dm_report_field *field, const void *data,			 void *private __attribute((unused))){	const char *name = dm_task_get_name((const struct dm_task *) data);	return dm_report_field_string(rh, field, &name);}static int _dm_uuid_disp(struct dm_report *rh,			 struct dm_pool *mem __attribute((unused)),			 struct dm_report_field *field,			 const void *data, void *private __attribute((unused))){	const char *uuid = dm_task_get_uuid((const struct dm_task *) data);	if (!uuid || !*uuid)		uuid = "";	return dm_report_field_string(rh, field, &uuid);}static int _dm_info_status_disp(struct dm_report *rh,				struct dm_pool *mem __attribute((unused)),				struct dm_report_field *field, const void *data,				void *private __attribute((unused))){	char buf[5];	const char *s = buf;	const struct dm_info *info = data;	buf[0] = info->live_table ? 'L' : '-';	buf[1] = info->inactive_table ? 'I' : '-';	buf[2] = info->suspended ? 's' : '-';	buf[3] = info->read_only ? 'r' : 'w';	buf[4] = '\0';	return dm_report_field_string(rh, field, &s);}static int _dm_info_devno_disp(struct dm_report *rh, struct dm_pool *mem,			       struct dm_report_field *field, const void *data,			       void *private){	char buf[DM_MAX_TYPE_NAME], *repstr;	struct dm_info *info = (struct dm_info *) data;	if (!dm_pool_begin_object(mem, 8)) {		log_error("dm_pool_begin_object failed");		return 0;	}	if (dm_snprintf(buf, sizeof(buf), "%d:%d",			info->major, info->minor) < 0) {		log_error("dm_pool_alloc failed");		goto out_abandon;	}	if (!dm_pool_grow_object(mem, buf, strlen(buf) + 1)) {		log_error("dm_pool_grow_object failed");		goto out_abandon;	}	repstr = dm_pool_end_object(mem);	dm_report_field_set_value(field, repstr, repstr);	return 1;      out_abandon:	dm_pool_abandon_object(mem);	return 0;}static int _dm_tree_names(struct dm_report *rh, struct dm_pool *mem,			  struct dm_report_field *field, const void *data,			  void *private, unsigned inverted){	struct dm_tree_node *node = (struct dm_tree_node *) data, *parent;	void *t = NULL;	const char *name;	int first_node = 1;	char *repstr;	if (!dm_pool_begin_object(mem, 16)) {		log_error("dm_pool_begin_object failed");		return 0;	}	while ((parent = dm_tree_next_child(&t, node, inverted))) {		name = dm_tree_node_get_name(parent);		if (!name || !*name)			continue;		if (!first_node && !dm_pool_grow_object(mem, ",", 1)) {			log_error("dm_pool_grow_object failed");			goto out_abandon;		}		if (!dm_pool_grow_object(mem, name, strlen(name))) {			log_error("dm_pool_grow_object failed");			goto out_abandon;		}		if (first_node)			first_node = 0;	}	if (!dm_pool_grow_object(mem, "\0", 1)) {		log_error("dm_pool_grow_object failed");		goto out_abandon;	}	repstr = dm_pool_end_object(mem);	dm_report_field_set_value(field, repstr, repstr);	return 1;      out_abandon:	dm_pool_abandon_object(mem);	return 0;}static int _dm_deps_names_disp(struct dm_report *rh,				      struct dm_pool *mem,				      struct dm_report_field *field,				      const void *data, void *private){	return _dm_tree_names(rh, mem, field, data, private, 0);}static int _dm_tree_parents_names_disp(struct dm_report *rh,				       struct dm_pool *mem,				       struct dm_report_field *field,				       const void *data, void *private){	return _dm_tree_names(rh, mem, field, data, private, 1);}static int _dm_tree_parents_devs_disp(struct dm_report *rh, struct dm_pool *mem,				      struct dm_report_field *field,				      const void *data, void *private){	struct dm_tree_node *node = (struct dm_tree_node *) data, *parent;	void *t = NULL;	const struct dm_info *info;	int first_node = 1;	char buf[DM_MAX_TYPE_NAME], *repstr;	if (!dm_pool_begin_object(mem, 16)) {		log_error("dm_pool_begin_object failed");		return 0;	}	while ((parent = dm_tree_next_child(&t, node, 1))) {		info = dm_tree_node_get_info(parent);		if (!info->major && !info->minor)			continue;		if (!first_node && !dm_pool_grow_object(mem, ",", 1)) {			log_error("dm_pool_grow_object failed");			goto out_abandon;		}		if (dm_snprintf(buf, sizeof(buf), "%d:%d",				info->major, info->minor) < 0) {			log_error("dm_snprintf failed");			goto out_abandon;		}		if (!dm_pool_grow_object(mem, buf, strlen(buf))) {			log_error("dm_pool_grow_object failed");			goto out_abandon;		}		if (first_node)			first_node = 0;	}	if (!dm_pool_grow_object(mem, "\0", 1)) {		log_error("dm_pool_grow_object failed");		goto out_abandon;	}	repstr = dm_pool_end_object(mem);	dm_report_field_set_value(field, repstr, repstr);	return 1;      out_abandon:	dm_pool_abandon_object(mem);	return 0;}static int _dm_tree_parents_count_disp(struct dm_report *rh,				       struct dm_pool *mem,				       struct dm_report_field *field,				       const void *data, void *private){	struct dm_tree_node *node = (struct dm_tree_node *) data;	int num_parent = dm_tree_node_num_children(node, 1);	return dm_report_field_int(rh, field, &num_parent);}static int _dm_deps_disp(struct dm_report *rh, struct dm_pool *mem,			 struct dm_report_field *field, const void *data,			 void *private){	struct dm_deps *deps = (struct dm_deps *) data;	int i;	char buf[DM_MAX_TYPE_NAME], *repstr;	if (!dm_pool_begin_object(mem, 16)) {		log_error("dm_pool_begin_object failed");		return 0;	}	for (i = 0; i < deps->count; i++) {		if (dm_snprintf(buf, sizeof(buf), "%d:%d",		       (int) MAJOR(deps->device[i]),		       (int) MINOR(deps->device[i])) < 0) {			log_error("dm_snprintf failed");			goto out_abandon;		}		if (!dm_pool_grow_object(mem, buf, strlen(buf))) {			log_error("dm_pool_grow_object failed");			goto out_abandon;		}		if (i + 1 < deps->count && !dm_pool_grow_object(mem, ",", 1)) {			log_error("dm_pool_grow_object failed");			goto out_abandon;		}	}	if (!dm_pool_grow_object(mem, "\0", 1)) {		log_error("dm_pool_grow_object failed");		goto out_abandon;	}	repstr = dm_pool_end_object(mem);	dm_report_field_set_value(field, repstr, repstr);	return 1;      out_abandon:	dm_pool_abandon_object(mem);	return 0;}static void *_task_get_obj(void *obj){	return ((struct dmsetup_report_obj *)obj)->task;}static void *_info_get_obj(void *obj){	return ((struct dmsetup_report_obj *)obj)->info;}static void *_deps_get_obj(void *obj){	return dm_task_get_deps(((struct dmsetup_report_obj *)obj)->deps_task);}static void *_tree_get_obj(void *obj){	return ((struct dmsetup_report_obj *)obj)->tree_node;}static const struct dm_report_object_type _report_types[] = {	{ DR_TASK, "Mapped Device Name", "", _task_get_obj },	{ DR_INFO, "Mapped Device Information", "", _info_get_obj },	{ DR_DEPS, "Mapped Device Relationship Information", "", _deps_get_obj },	{ DR_TREE, "Mapped Device Relationship Information", "", _tree_get_obj },	{ 0, "", "", NULL },};/* Column definitions */#define OFFSET_OF(strct, field) ((unsigned int) &((struct strct *)NULL)->field)#define STR (DM_REPORT_FIELD_TYPE_STRING)#define NUM (DM_REPORT_FIELD_TYPE_NUMBER)#define FIELD_O(type, strct, sorttype, head, field, width, func, id, desc) {DR_ ## type, sorttype, OFFSET_OF(strct, field), width, id, head, &_ ## func ## _disp, desc},#define FIELD_F(type, sorttype, head, width, func, id, desc) {DR_ ## type, sorttype, 0, width, id, head, &_ ## func ## _disp, desc},static const struct dm_report_field_type _report_fields[] = {/* *INDENT-OFF* */FIELD_F(TASK, STR, "Name", 16, dm_name, "name", "Name of mapped device.")FIELD_F(TASK, STR, "UUID", 32, dm_uuid, "uuid", "Unique (optional) identifier for mapped device.")FIELD_F(INFO, STR, "Stat", 4, dm_info_status, "attr", "(L)ive, (I)nactive, (s)uspended, (r)ead-only, read-(w)rite.")FIELD_F(INFO, STR, "DevNo", 5, dm_info_devno, "devno", "Device major and minor numbers")FIELD_O(INFO, dm_info, NUM, "Maj", major, 3, int32, "major", "Block device major number.")FIELD_O(INFO, dm_info, NUM, "Min", minor, 3, int32, "minor", "Block device minor number.")FIELD_O(INFO, dm_info, NUM, "Open", open_count, 4, int32, "open", "Number of references to open device, if requested.")FIELD_O(INFO, dm_info, NUM, "Targ", target_count, 4, int32, "segments", "Number of segments in live table, if present.")FIELD_O(INFO, dm_info, NUM, "Event", event_nr, 6, uint32, "events", "Number of most recent event.")FIELD_O(DEPS, dm_deps, NUM, "#Devs", count, 5, int32, "device_count", "Number of devices used by this one.")FIELD_F(TREE, STR, "DevNames", 8, dm_deps_names, "devs_used", "List of names of mapped devices used by this one.")FIELD_F(DEPS, STR, "DevNos", 6, dm_deps, "devnos_used", "List of device numbers of devices used by this one.")FIELD_F(TREE, NUM, "#Refs", 5, dm_tree_parents_count, "device_ref_count", "Number of mapped devices referencing this one.")FIELD_F(TREE, STR, "RefNames", 8, dm_tree_parents_names, "names_using_dev", "List of names of mapped devices using this one.")FIELD_F(TREE, STR, "RefDevNos", 9, dm_tree_parents_devs, "devnos_using_dev", "List of device numbers of mapped devices using this one."){0, 0, 0, 0, "", "", NULL, NULL},/* *INDENT-ON* */};#undef STR#undef NUM#undef FIELD_O#undef FIELD_Fstatic const char *default_report_options = "name,major,minor,attr,open,segments,events,uuid";static int _report_init(struct command *c){	char *options = (char *) default_report_options;	const char *keys = "";	const char *separator = " ";	int aligned = 1, headings = 1, buffered = 1;	uint32_t flags = 0;	size_t len = 0;	int r = 0;	/* emulate old dmsetup behaviour */	if (_switches[NOHEADINGS_ARG]) {		separator = ":";		aligned = 0;		headings = 0;	}	if (_switches[UNBUFFERED_ARG])		buffered = 0;	if (_switches[OPTIONS_ARG] && _string_args[OPTIONS_ARG]) {		if (*_string_args[OPTIONS_ARG] != '+')			options = _string_args[OPTIONS_ARG];		else {			len = strlen(default_report_options) +			      strlen(_string_args[OPTIONS_ARG]) + 1;			if (!(options = dm_malloc(len))) {				err("Failed to allocate option string.");				return 0;			}			if (dm_snprintf(options, len, "%s,%s",					default_report_options,					&_string_args[OPTIONS_ARG][1]) < 0) {				err("snprintf failed");				goto out;			}		}	}	if (_switches[SORT_ARG] && _string_args[SORT_ARG]) {		keys = _string_args[SORT_ARG];		buffered = 1;		if (c && (!strcmp(c->name, "status") || !strcmp(c->name, "table"))) {			err("--sort is not yet supported with status and table");			goto out;		}	}	if (_switches[SEPARATOR_ARG] && _string_args[SEPARATOR_ARG]) {		separator = _string_args[SEPARATOR_ARG];		aligned = 0;	}	if (aligned)		flags |= DM_REPORT_OUTPUT_ALIGNED;	if (buffered)		flags |= DM_REPORT_OUTPUT_BUFFERED;	if (headings)		flags |= DM_REPORT_OUTPUT_HEADINGS;	if (!(_report = dm_report_init(&_report_type,				       _report_types, _report_fields,				       options, separator, flags, keys, NULL)))		goto out;	if ((_report_type & DR_TREE) && !_build_whole_deptree()) {		err("Internal device dependency tree creation failed.");		goto out;	}

⌨️ 快捷键说明

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