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

📄 dmsetup.c

📁 Linux Device Mapper Source Code
💻 C
📖 第 1 页 / 共 4 页
字号:
/* * Copyright (C) 2001-2004 Sistina Software, Inc. All rights reserved. * Copyright (C) 2004-2007 Red Hat, Inc. All rights reserved. * Copyright (C) 2005-2007 NEC Corporation * * This file is part of the device-mapper userspace tools. * * It includes tree drawing code based on pstree: http://psmisc.sourceforge.net/ * * 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 General Public License v.2. * * You should have received a copy of the GNU 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 */#define _GNU_SOURCE#define _FILE_OFFSET_BITS 64#include "configure.h"#include "libdevmapper.h"#include "log.h"#include <stdio.h>#include <stdlib.h>#include <string.h>#include <ctype.h>#include <dirent.h>#include <errno.h>#include <unistd.h>#include <libgen.h>#include <sys/wait.h>#include <unistd.h>#include <sys/param.h>#include <locale.h>#include <langinfo.h>#include <fcntl.h>#include <sys/stat.h>/* FIXME Unused so far */#undef HAVE_SYS_STATVFS_H#ifdef HAVE_SYS_STATVFS_H#  include <sys/statvfs.h>#endif#ifdef HAVE_SYS_IOCTL_H#  include <sys/ioctl.h>#endif#if HAVE_TERMIOS_H#  include <termios.h>#endif#ifdef HAVE_GETOPTLONG#  include <getopt.h>#  define GETOPTLONG_FN(a, b, c, d, e) getopt_long((a), (b), (c), (d), (e))#  define OPTIND_INIT 0#elsestruct option {};extern int optind;extern char *optarg;#  define GETOPTLONG_FN(a, b, c, d, e) getopt((a), (b), (c))#  define OPTIND_INIT 1#endif#ifndef TEMP_FAILURE_RETRY# define TEMP_FAILURE_RETRY(expression) \  (__extension__                                                              \    ({ long int __result;                                                     \       do __result = (long int) (expression);                                 \       while (__result == -1L && errno == EINTR);                             \       __result; }))#endif#ifdef linux#  include "kdev_t.h"#else#  define MAJOR(x) major((x))#  define MINOR(x) minor((x))#  define MKDEV(x,y) makedev((x),(y))#endif#define LINE_SIZE 4096#define ARGS_MAX 256#define LOOP_TABLE_SIZE (PATH_MAX + 255)/* FIXME Should be imported */#ifndef DM_MAX_TYPE_NAME#  define DM_MAX_TYPE_NAME 16#endif/* FIXME Should be elsewhere */#define SECTOR_SHIFT 9L#define DEV_PATH "/dev/"#define err(msg, x...) fprintf(stderr, msg "\n", ##x)/* * We have only very simple switches ATM. */enum {	READ_ONLY = 0,	COLS_ARG,	EXEC_ARG,	FORCE_ARG,	GID_ARG,	MAJOR_ARG,	MINOR_ARG,	MODE_ARG,	NOFLUSH_ARG,	NOHEADINGS_ARG,	NOLOCKFS_ARG,	NOOPENCOUNT_ARG,	NOTABLE_ARG,	OPTIONS_ARG,	SEPARATOR_ARG,	SHOWKEYS_ARG,	SORT_ARG,	TABLE_ARG,	TARGET_ARG,	TREE_ARG,	UID_ARG,	UNBUFFERED_ARG,	UUID_ARG,	VERBOSE_ARG,	VERSION_ARG,	NUM_SWITCHES};typedef enum {	DR_TASK = 1,	DR_INFO = 2,	DR_DEPS = 4,	DR_TREE = 8	/* Complete dependency tree required */} report_type_t;static int _switches[NUM_SWITCHES];static int _int_args[NUM_SWITCHES];static char *_string_args[NUM_SWITCHES];static int _num_devices;static char *_uuid;static char *_table;static char *_target;static char *_command;static struct dm_tree *_dtree;static struct dm_report *_report;static report_type_t _report_type;/* * Commands */typedef int (*command_fn) (int argc, char **argv, void *data);struct command {	const char *name;	const char *help;	int min_args;	int max_args;	command_fn fn;};static int _parse_line(struct dm_task *dmt, char *buffer, const char *file,		       int line){	char ttype[LINE_SIZE], *ptr, *comment;	unsigned long long start, size;	int n;	/* trim trailing space */	for (ptr = buffer + strlen(buffer) - 1; ptr >= buffer; ptr--)		if (!isspace((int) *ptr))			break;	ptr++;	*ptr = '\0';	/* trim leading space */	for (ptr = buffer; *ptr && isspace((int) *ptr); ptr++)		;	if (!*ptr || *ptr == '#')		return 1;	if (sscanf(ptr, "%llu %llu %s %n",		   &start, &size, ttype, &n) < 3) {		err("Invalid format on line %d of table %s", line, file);		return 0;	}	ptr += n;	if ((comment = strchr(ptr, (int) '#')))		*comment = '\0';	if (!dm_task_add_target(dmt, start, size, ttype, ptr))		return 0;	return 1;}static int _parse_file(struct dm_task *dmt, const char *file){	char *buffer = NULL;	size_t buffer_size = 0;	FILE *fp;	int r = 0, line = 0;	/* one-line table on cmdline */	if (_table)		return _parse_line(dmt, _table, "", ++line);	/* OK for empty stdin */	if (file) {		if (!(fp = fopen(file, "r"))) {			err("Couldn't open '%s' for reading", file);			return 0;		}	} else		fp = stdin;#ifndef HAVE_GETLINE	buffer_size = LINE_SIZE;	if (!(buffer = dm_malloc(buffer_size))) {		err("Failed to malloc line buffer.");		return 0;	}	while (fgets(buffer, (int) buffer_size, fp))#else	while (getline(&buffer, &buffer_size, fp) > 0)#endif		if (!_parse_line(dmt, buffer, file ? : "on stdin", ++line))			goto out;	r = 1;      out:#ifndef HAVE_GETLINE	dm_free(buffer);#else	free(buffer);#endif	if (file && fclose(fp))		fprintf(stderr, "%s: fclose failed: %s", file, strerror(errno));	return r;}struct dmsetup_report_obj {	struct dm_task *task;	struct dm_info *info;	struct dm_task *deps_task;	struct dm_tree_node *tree_node;};static struct dm_task *_get_deps_task(int major, int minor){	struct dm_task *dmt;	struct dm_info info;	if (!(dmt = dm_task_create(DM_DEVICE_DEPS)))		return NULL;	if (!dm_task_set_major(dmt, major) ||	    !dm_task_set_minor(dmt, minor))		goto err;	if (_switches[NOOPENCOUNT_ARG] && !dm_task_no_open_count(dmt))		goto err;	if (!dm_task_run(dmt))		goto err;	if (!dm_task_get_info(dmt, &info))		goto err;	if (!info.exists)		goto err;	return dmt;      err:	dm_task_destroy(dmt);	return NULL;}static int _display_info_cols(struct dm_task *dmt, struct dm_info *info){	struct dmsetup_report_obj obj;	int r = 0;	if (!info->exists) {		fprintf(stderr, "Device does not exist.\n");		return 0;	}	obj.task = dmt;	obj.info = info;	obj.deps_task = NULL;	if (_report_type & DR_TREE)		obj.tree_node = dm_tree_find_node(_dtree, info->major, info->minor);	if (_report_type & DR_DEPS)		obj.deps_task = _get_deps_task(info->major, info->minor);	if (!dm_report_object(_report, &obj))		goto out;	r = 1;      out:	if (obj.deps_task)		dm_task_destroy(obj.deps_task);	return r;}static void _display_info_long(struct dm_task *dmt, struct dm_info *info){	const char *uuid;	if (!info->exists) {		printf("Device does not exist.\n");		return;	}	printf("Name:              %s\n", dm_task_get_name(dmt));	printf("State:             %s%s\n",	       info->suspended ? "SUSPENDED" : "ACTIVE",	       info->read_only ? " (READ-ONLY)" : "");	if (!info->live_table && !info->inactive_table)		printf("Tables present:    None\n");	else		printf("Tables present:    %s%s%s\n",		       info->live_table ? "LIVE" : "",		       info->live_table && info->inactive_table ? " & " : "",		       info->inactive_table ? "INACTIVE" : "");	if (info->open_count != -1)		printf("Open count:        %d\n", info->open_count);	printf("Event number:      %" PRIu32 "\n", info->event_nr);	printf("Major, minor:      %d, %d\n", info->major, info->minor);	if (info->target_count != -1)		printf("Number of targets: %d\n", info->target_count);	if ((uuid = dm_task_get_uuid(dmt)) && *uuid)		printf("UUID: %s\n", uuid);	printf("\n");}static int _display_info(struct dm_task *dmt){	struct dm_info info;	if (!dm_task_get_info(dmt, &info))		return 0;	if (!_switches[COLS_ARG])		_display_info_long(dmt, &info);	else		/* FIXME return code */		_display_info_cols(dmt, &info);	return info.exists ? 1 : 0;}static int _set_task_device(struct dm_task *dmt, const char *name, int optional){	if (name) {		if (!dm_task_set_name(dmt, name))			return 0;	} else if (_switches[UUID_ARG]) {		if (!dm_task_set_uuid(dmt, _uuid))			return 0;	} else if (_switches[MAJOR_ARG] && _switches[MINOR_ARG]) {		if (!dm_task_set_major(dmt, _int_args[MAJOR_ARG]) ||		    !dm_task_set_minor(dmt, _int_args[MINOR_ARG]))			return 0;	} else if (!optional) {		fprintf(stderr, "No device specified.\n");		return 0;	}	return 1;}static int _load(int argc, char **argv, void *data __attribute((unused))){	int r = 0;	struct dm_task *dmt;	const char *file = NULL;	const char *name = NULL;	if (_switches[NOTABLE_ARG]) {		err("--notable only available when creating new device\n");		return 0;	}	if (!_switches[UUID_ARG] && !_switches[MAJOR_ARG]) {		if (argc == 1) {			err("Please specify device.\n");			return 0;		}		name = argv[1];		argc--;		argv++;	} else if (argc > 2) {		err("Too many command line arguments.\n");		return 0;	}	if (argc == 2)		file = argv[1];	if (!(dmt = dm_task_create(DM_DEVICE_RELOAD)))		return 0;	if (!_set_task_device(dmt, name, 0))		goto out;	if (!_switches[NOTABLE_ARG] && !_parse_file(dmt, file))		goto out;	if (_switches[READ_ONLY] && !dm_task_set_ro(dmt))		goto out;	if (_switches[NOOPENCOUNT_ARG] && !dm_task_no_open_count(dmt))		goto out;	if (!dm_task_run(dmt))		goto out;	r = 1;	if (_switches[VERBOSE_ARG])		r = _display_info(dmt);      out:	dm_task_destroy(dmt);	return r;}static int _create(int argc, char **argv, void *data __attribute((unused))){	int r = 0;	struct dm_task *dmt;	const char *file = NULL;	if (argc == 3)		file = argv[2];	if (!(dmt = dm_task_create(DM_DEVICE_CREATE)))		return 0;	if (!dm_task_set_name(dmt, argv[1]))		goto out;	if (_switches[UUID_ARG] && !dm_task_set_uuid(dmt, _uuid))		goto out;	if (!_switches[NOTABLE_ARG] && !_parse_file(dmt, file))		goto out;	if (_switches[READ_ONLY] && !dm_task_set_ro(dmt))		goto out;	if (_switches[MAJOR_ARG] && !dm_task_set_major(dmt, _int_args[MAJOR_ARG]))		goto out;	if (_switches[MINOR_ARG] && !dm_task_set_minor(dmt, _int_args[MINOR_ARG]))		goto out;	if (_switches[UID_ARG] && !dm_task_set_uid(dmt, _int_args[UID_ARG]))		goto out;	if (_switches[GID_ARG] && !dm_task_set_gid(dmt, _int_args[GID_ARG]))		goto out;	if (_switches[MODE_ARG] && !dm_task_set_mode(dmt, _int_args[MODE_ARG]))		goto out;	if (_switches[NOOPENCOUNT_ARG] && !dm_task_no_open_count(dmt))		goto out;	if (!dm_task_run(dmt))		goto out;	r = 1;	if (_switches[VERBOSE_ARG])		r = _display_info(dmt);      out:	dm_task_destroy(dmt);	return r;}static int _rename(int argc, char **argv, void *data __attribute((unused))){	int r = 0;	struct dm_task *dmt;	if (!(dmt = dm_task_create(DM_DEVICE_RENAME)))		return 0;	/* FIXME Kernel doesn't support uuid or device number here yet */	if (!_set_task_device(dmt, (argc == 3) ? argv[1] : NULL, 0))		goto out;	if (!dm_task_set_newname(dmt, argv[argc - 1]))		goto out;	if (_switches[NOOPENCOUNT_ARG] && !dm_task_no_open_count(dmt))		goto out;	if (!dm_task_run(dmt))		goto out;	r = 1;      out:	dm_task_destroy(dmt);	return r;}static int _message(int argc, char **argv, void *data __attribute((unused))){	int r = 0, i;	size_t sz = 1;	struct dm_task *dmt;	char *str;	if (!(dmt = dm_task_create(DM_DEVICE_TARGET_MSG)))		return 0;	if (_switches[UUID_ARG] || _switches[MAJOR_ARG]) {		if (!_set_task_device(dmt, NULL, 0))			goto out;	} else {		if (!_set_task_device(dmt, argv[1], 0))			goto out;		argc--;		argv++;	}	if (!dm_task_set_sector(dmt, (uint64_t) atoll(argv[1])))		goto out;	argc -= 2;	argv += 2;	if (argc <= 0)		err("No message supplied.\n");	for (i = 0; i < argc; i++)		sz += strlen(argv[i]) + 1;	if (!(str = dm_malloc(sz))) {		err("message string allocation failed");		goto out;	}	memset(str, 0, sz);	for (i = 0; i < argc; i++) {		if (i)			strcat(str, " ");		strcat(str, argv[i]);	}	if (!dm_task_set_message(dmt, str))		goto out;	dm_free(str);	if (_switches[NOOPENCOUNT_ARG] && !dm_task_no_open_count(dmt))		goto out;	if (!dm_task_run(dmt))		goto out;	r = 1;      out:	dm_task_destroy(dmt);	return r;}static int _setgeometry(int argc, char **argv, void *data __attribute((unused))){	int r = 0;	struct dm_task *dmt;	if (!(dmt = dm_task_create(DM_DEVICE_SET_GEOMETRY)))		return 0;	if (_switches[UUID_ARG] || _switches[MAJOR_ARG]) {		if (!_set_task_device(dmt, NULL, 0))			goto out;	} else {		if (!_set_task_device(dmt, argv[1], 0))			goto out;		argc--;		argv++;	}	if (!dm_task_set_geometry(dmt, argv[1], argv[2], argv[3], argv[4]))		goto out;	/* run the task */	if (!dm_task_run(dmt))		goto out;	r = 1;      out:	dm_task_destroy(dmt);	return r;}static int _version(int argc __attribute((unused)), char **argv __attribute((unused)), void *data __attribute((unused))){	char version[80];	if (dm_get_library_version(version, sizeof(version)))		printf("Library version:   %s\n", version);	if (!dm_driver_version(version, sizeof(version)))		return 0;	printf("Driver version:    %s\n", version);	return 1;}

⌨️ 快捷键说明

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