summaryrefslogtreecommitdiff
path: root/tools/dmsetup.c
diff options
context:
space:
mode:
Diffstat (limited to 'tools/dmsetup.c')
-rw-r--r--tools/dmsetup.c1002
1 files changed, 728 insertions, 274 deletions
diff --git a/tools/dmsetup.c b/tools/dmsetup.c
index 2eeee7f..196c170 100644
--- a/tools/dmsetup.c
+++ b/tools/dmsetup.c
@@ -1,6 +1,6 @@
/*
* Copyright (C) 2001-2004 Sistina Software, Inc. All rights reserved.
- * Copyright (C) 2004-2008 Red Hat, Inc. All rights reserved.
+ * Copyright (C) 2004-2012 Red Hat, Inc. All rights reserved.
* Copyright (C) 2005-2007 NEC Corporation
*
* This file is part of the device-mapper userspace tools.
@@ -30,7 +30,6 @@
#include <dirent.h>
#include <errno.h>
#include <unistd.h>
-#include <libgen.h>
#include <sys/wait.h>
#include <unistd.h>
#include <sys/param.h>
@@ -45,7 +44,6 @@
# include <sys/types.h>
# include <sys/ipc.h>
# include <sys/sem.h>
-# define LIBUDEV_I_KNOW_THE_API_IS_SUBJECT_TO_CHANGE
# include <libudev.h>
#endif
@@ -118,12 +116,16 @@ extern char *optarg;
*/
enum {
READ_ONLY = 0,
+ ADD_NODE_ON_CREATE_ARG,
+ ADD_NODE_ON_RESUME_ARG,
+ CHECKS_ARG,
COLS_ARG,
EXEC_ARG,
FORCE_ARG,
GID_ARG,
HELP_ARG,
INACTIVE_ARG,
+ MANGLENAME_ARG,
MAJOR_ARG,
MINOR_ARG,
MODE_ARG,
@@ -138,6 +140,7 @@ enum {
NOUDEVSYNC_ARG,
OPTIONS_ARG,
READAHEAD_ARG,
+ RETRY_ARG,
ROWS_ARG,
SEPARATOR_ARG,
SETUUID_ARG,
@@ -151,6 +154,7 @@ enum {
UNQUOTED_ARG,
UUID_ARG,
VERBOSE_ARG,
+ VERIFYUDEV_ARG,
VERSION_ARG,
YES_ARG,
NUM_SWITCHES
@@ -164,6 +168,12 @@ typedef enum {
DR_NAME = 16
} report_type_t;
+typedef enum {
+ DN_DEVNO, /* Major and minor number pair */
+ DN_BLK, /* Block device name (e.g. dm-0) */
+ DN_MAP /* Map name (for dm devices only, equal to DN_BLK otherwise) */
+} dev_name_t;
+
static int _switches[NUM_SWITCHES];
static int _int_args[NUM_SWITCHES];
static char *_string_args[NUM_SWITCHES];
@@ -178,18 +188,22 @@ static int _udev_only;
static struct dm_tree *_dtree;
static struct dm_report *_report;
static report_type_t _report_type;
+static dev_name_t _dev_name_type;
/*
* Commands
*/
-typedef int (*command_fn) (int argc, char **argv, void *data);
+struct command;
+#define CMD_ARGS const struct command *cmd, int argc, char **argv, struct dm_names *names, int multiple_devices
+typedef int (*command_fn) (CMD_ARGS);
struct command {
const char *name;
const char *help;
int min_args;
int max_args;
+ int repeatable_cmd; /* Repeat to process device list? */
command_fn fn;
};
@@ -312,6 +326,9 @@ static struct dm_task *_get_deps_task(int major, int minor)
if (_switches[INACTIVE_ARG] && !dm_task_query_inactive_table(dmt))
goto err;
+ if (_switches[CHECKS_ARG] && !dm_task_enable_checks(dmt))
+ goto err;
+
if (!dm_task_run(dmt))
goto err;
@@ -362,7 +379,11 @@ static struct dm_split_name *_get_split_name(const char *uuid, const char *name,
return NULL;
}
- split_name->subsystem = _extract_uuid_prefix(uuid, separator);
+ if (!(split_name->subsystem = _extract_uuid_prefix(uuid, separator))) {
+ dm_free(split_name);
+ return_NULL;
+ }
+
split_name->vg_name = split_name->lv_name =
split_name->lv_layer = (char *) "";
@@ -405,16 +426,24 @@ static int _display_info_cols(struct dm_task *dmt, struct dm_info *info)
obj.split_name = NULL;
if (_report_type & DR_TREE)
- obj.tree_node = dm_tree_find_node(_dtree, info->major, info->minor);
+ if (!(obj.tree_node = dm_tree_find_node(_dtree, info->major, info->minor))) {
+ log_error("Cannot find node %d:%d.", info->major, info->minor);
+ goto out;
+ }
if (_report_type & DR_DEPS)
- obj.deps_task = _get_deps_task(info->major, info->minor);
+ if (!(obj.deps_task = _get_deps_task(info->major, info->minor))) {
+ log_error("Cannot get deps for %d:%d.", info->major, info->minor);
+ goto out;
+ }
if (_report_type & DR_NAME)
- obj.split_name = _get_split_name(dm_task_get_uuid(dmt), dm_task_get_name(dmt), '-');
+ if (!(obj.split_name = _get_split_name(dm_task_get_uuid(dmt),
+ dm_task_get_name(dmt), '-')))
+ goto_out;
if (!dm_report_object(_report, &obj))
- goto out;
+ goto_out;
r = 1;
@@ -505,7 +534,23 @@ static int _set_task_device(struct dm_task *dmt, const char *name, int optional)
return 1;
}
-static int _load(int argc, char **argv, void *data __attribute__((unused)))
+static int _set_task_add_node(struct dm_task *dmt)
+{
+ if (!dm_task_set_add_node(dmt, DEFAULT_DM_ADD_NODE))
+ return 0;
+
+ if (_switches[ADD_NODE_ON_RESUME_ARG] &&
+ !dm_task_set_add_node(dmt, DM_ADD_NODE_ON_RESUME))
+ return 0;
+
+ if (_switches[ADD_NODE_ON_CREATE_ARG] &&
+ !dm_task_set_add_node(dmt, DM_ADD_NODE_ON_CREATE))
+ return 0;
+
+ return 1;
+}
+
+static int _load(CMD_ARGS)
{
int r = 0;
struct dm_task *dmt;
@@ -551,6 +596,9 @@ static int _load(int argc, char **argv, void *data __attribute__((unused)))
if (_switches[INACTIVE_ARG] && !dm_task_query_inactive_table(dmt))
goto out;
+ if (_switches[CHECKS_ARG] && !dm_task_enable_checks(dmt))
+ goto out;
+
if (!dm_task_run(dmt))
goto out;
@@ -565,7 +613,7 @@ static int _load(int argc, char **argv, void *data __attribute__((unused)))
return r;
}
-static int _create(int argc, char **argv, void *data __attribute__((unused)))
+static int _create(CMD_ARGS)
{
int r = 0;
struct dm_task *dmt;
@@ -624,11 +672,17 @@ static int _create(int argc, char **argv, void *data __attribute__((unused)))
udev_flags |= DM_UDEV_DISABLE_DM_RULES_FLAG |
DM_UDEV_DISABLE_SUBSYSTEM_RULES_FLAG;
- if (_udev_cookie) {
+ if (_switches[CHECKS_ARG] && !dm_task_enable_checks(dmt))
+ goto out;
+
+ if (!_set_task_add_node(dmt))
+ goto out;
+
+ if (_udev_cookie)
cookie = _udev_cookie;
- if (_udev_only)
- udev_flags |= DM_UDEV_DISABLE_LIBRARY_FALLBACK;
- }
+
+ if (_udev_only)
+ udev_flags |= DM_UDEV_DISABLE_LIBRARY_FALLBACK;
if (!dm_task_set_cookie(dmt, &cookie, udev_flags) ||
!dm_task_run(dmt))
@@ -636,26 +690,19 @@ static int _create(int argc, char **argv, void *data __attribute__((unused)))
r = 1;
+ out:
if (!_udev_cookie)
(void) dm_udev_wait(cookie);
- if (_switches[VERBOSE_ARG])
+ if (r && _switches[VERBOSE_ARG])
r = _display_info(dmt);
dm_task_destroy(dmt);
return r;
-
- out:
- if (!_udev_cookie)
- (void) dm_udev_wait(cookie);
- dm_task_destroy(dmt);
-
- return r;
}
-static int _rename(int argc, char **argv, void *data __attribute__((unused)))
-{
+static int _do_rename(const char *name, const char *new_name, const char *new_uuid) {
int r = 0;
struct dm_task *dmt;
uint32_t cookie = 0;
@@ -665,13 +712,13 @@ static int _rename(int argc, char **argv, void *data __attribute__((unused)))
return 0;
/* FIXME Kernel doesn't support uuid or device number here yet */
- if (!_set_task_device(dmt, (argc == 3) ? argv[1] : NULL, 0))
+ if (!_set_task_device(dmt, name, 0))
goto out;
- if (_switches[SETUUID_ARG]) {
- if (!dm_task_set_newuuid(dmt, argv[argc - 1]))
+ if (new_uuid) {
+ if (!dm_task_set_newuuid(dmt, new_uuid))
goto out;
- } else if (!dm_task_set_newname(dmt, argv[argc - 1]))
+ } else if (!new_name || !dm_task_set_newname(dmt, new_name))
goto out;
if (_switches[NOOPENCOUNT_ARG] && !dm_task_no_open_count(dmt))
@@ -680,15 +727,18 @@ static int _rename(int argc, char **argv, void *data __attribute__((unused)))
if (_switches[INACTIVE_ARG] && !dm_task_query_inactive_table(dmt))
goto out;
+ if (_switches[CHECKS_ARG] && !dm_task_enable_checks(dmt))
+ goto out;
+
if (_switches[NOUDEVRULES_ARG])
udev_flags |= DM_UDEV_DISABLE_DM_RULES_FLAG |
DM_UDEV_DISABLE_SUBSYSTEM_RULES_FLAG;
- if (_udev_cookie) {
+ if (_udev_cookie)
cookie = _udev_cookie;
- if (_udev_only)
- udev_flags |= DM_UDEV_DISABLE_LIBRARY_FALLBACK;
- }
+
+ if (_udev_only)
+ udev_flags |= DM_UDEV_DISABLE_LIBRARY_FALLBACK;
if (!dm_task_set_cookie(dmt, &cookie, udev_flags) ||
!dm_task_run(dmt))
@@ -699,12 +749,22 @@ static int _rename(int argc, char **argv, void *data __attribute__((unused)))
out:
if (!_udev_cookie)
(void) dm_udev_wait(cookie);
+
dm_task_destroy(dmt);
return r;
}
-static int _message(int argc, char **argv, void *data __attribute__((unused)))
+static int _rename(CMD_ARGS)
+{
+ const char *name = (argc == 3) ? argv[1] : NULL;
+
+ return _switches[SETUUID_ARG] ? _do_rename(name, NULL, argv[argc - 1]) :
+ _do_rename(name, argv[argc - 1], NULL);
+
+}
+
+static int _message(CMD_ARGS)
{
int r = 0, i;
size_t sz = 1;
@@ -747,17 +807,22 @@ static int _message(int argc, char **argv, void *data __attribute__((unused)))
strcat(str, argv[i]);
}
- if (!dm_task_set_message(dmt, str))
- goto out;
+ i = dm_task_set_message(dmt, str);
dm_free(str);
+ if (!i)
+ goto out;
+
if (_switches[NOOPENCOUNT_ARG] && !dm_task_no_open_count(dmt))
goto out;
if (_switches[INACTIVE_ARG] && !dm_task_query_inactive_table(dmt))
goto out;
+ if (_switches[CHECKS_ARG] && !dm_task_enable_checks(dmt))
+ goto out;
+
if (!dm_task_run(dmt))
goto out;
@@ -769,7 +834,7 @@ static int _message(int argc, char **argv, void *data __attribute__((unused)))
return r;
}
-static int _setgeometry(int argc, char **argv, void *data __attribute__((unused)))
+static int _setgeometry(CMD_ARGS)
{
int r = 0;
struct dm_task *dmt;
@@ -796,6 +861,9 @@ static int _setgeometry(int argc, char **argv, void *data __attribute__((unused)
if (_switches[INACTIVE_ARG] && !dm_task_query_inactive_table(dmt))
goto out;
+ if (_switches[CHECKS_ARG] && !dm_task_enable_checks(dmt))
+ goto out;
+
/* run the task */
if (!dm_task_run(dmt))
goto out;
@@ -808,7 +876,7 @@ static int _setgeometry(int argc, char **argv, void *data __attribute__((unused)
return r;
}
-static int _splitname(int argc, char **argv, void *data __attribute__((unused)))
+static int _splitname(CMD_ARGS)
{
struct dmsetup_report_obj obj;
int r = 1;
@@ -817,8 +885,9 @@ static int _splitname(int argc, char **argv, void *data __attribute__((unused)))
obj.info = NULL;
obj.deps_task = NULL;
obj.tree_node = NULL;
- obj.split_name = _get_split_name((argc == 3) ? argv[2] : "LVM",
- argv[1], '\0');
+ if (!(obj.split_name = _get_split_name((argc == 3) ? argv[2] : "LVM",
+ argv[1], '\0')))
+ return_0;
r = dm_report_object(_report, &obj);
_destroy_split_name(obj.split_name);
@@ -842,7 +911,7 @@ static uint32_t _get_cookie_value(const char *str_value)
return (uint32_t) value;
}
-static int _udevflags(int args, char **argv, void *data __attribute__((unused)))
+static int _udevflags(CMD_ARGS)
{
uint32_t cookie;
uint16_t flags;
@@ -884,7 +953,7 @@ static int _udevflags(int args, char **argv, void *data __attribute__((unused)))
return 1;
}
-static int _udevcomplete(int argc, char **argv, void *data __attribute__((unused)))
+static int _udevcomplete(CMD_ARGS)
{
uint32_t cookie;
@@ -907,32 +976,30 @@ static int _udevcomplete(int argc, char **argv, void *data __attribute__((unused
}
#ifndef UDEV_SYNC_SUPPORT
-static const char _cmd_not_supported[] = "Command not supported. Recompile with \"--enable-udev-sync\" to enable.";
+static const char _cmd_not_supported[] = "Command not supported. Recompile with \"--enable-udev_sync\" to enable.";
-static int _udevcreatecookie(int argc, char **argv,
- void *data __attribute__((unused)))
+static int _udevcreatecookie(CMD_ARGS)
{
log_error(_cmd_not_supported);
return 0;
}
-static int _udevreleasecookie(int argc, char **argv,
- void *data __attribute__((unused)))
+static int _udevreleasecookie(CMD_ARGS)
{
log_error(_cmd_not_supported);
return 0;
}
-static int _udevcomplete_all(int argc __attribute__((unused)), char **argv __attribute__((unused)), void *data __attribute__((unused)))
+static int _udevcomplete_all(CMD_ARGS)
{
log_error(_cmd_not_supported);
return 0;
}
-static int _udevcookies(int argc __attribute__((unused)), char **argv __attribute__((unused)), void *data __attribute__((unused)))
+static int _udevcookies(CMD_ARGS)
{
log_error(_cmd_not_supported);
@@ -942,11 +1009,9 @@ static int _udevcookies(int argc __attribute__((unused)), char **argv __attribut
#else /* UDEV_SYNC_SUPPORT */
static int _set_up_udev_support(const char *dev_dir)
{
- struct udev *udev;
- const char *udev_dev_dir;
- size_t udev_dev_dir_len;
int dirs_diff;
const char *env;
+ size_t len = strlen(dev_dir), udev_dir_len = strlen(DM_UDEV_DEV_DIR);
if (_switches[NOUDEVSYNC_ARG])
dm_udev_set_sync_support(0);
@@ -964,14 +1029,6 @@ static int _set_up_udev_support(const char *dev_dir)
" defined by --udevcookie option.",
_udev_cookie);
- if (!(udev = udev_new()) ||
- !(udev_dev_dir = udev_get_dev_path(udev)) ||
- !*udev_dev_dir) {
- log_error("Could not get udev dev path.");
- return 0;
- }
- udev_dev_dir_len = strlen(udev_dev_dir);
-
/*
* Normally, there's always a fallback action by libdevmapper if udev
* has not done its job correctly, e.g. the nodes were not created.
@@ -983,13 +1040,18 @@ static int _set_up_udev_support(const char *dev_dir)
* is the same as "dev path" used by libdevmapper.
*/
- /* There's always a slash at the end of dev_dir. But check udev_dev_dir! */
- if (udev_dev_dir[udev_dev_dir_len - 1] != '/')
- dirs_diff = strncmp(dev_dir, udev_dev_dir, udev_dev_dir_len);
- else
- dirs_diff = strcmp(dev_dir, udev_dev_dir);
- _udev_only = _udev_cookie && !dirs_diff;
+ /*
+ * DM_UDEV_DEV_DIR always has '/' at its end.
+ * If the dev_dir does not have it, be sure
+ * to make the right comparison without the '/' char!
+ */
+ if (dev_dir[len - 1] != '/')
+ udev_dir_len--;
+
+ dirs_diff = udev_dir_len != len ||
+ strncmp(DM_UDEV_DEV_DIR, dev_dir, len);
+ _udev_only = !dirs_diff && (_udev_cookie || !_switches[VERIFYUDEV_ARG]);
if (dirs_diff) {
log_debug("The path %s used for creating device nodes that is "
@@ -998,16 +1060,14 @@ static int _set_up_udev_support(const char *dev_dir)
"about udev not working correctly while processing "
"particular nodes will be suppressed. These nodes "
"and symlinks will be managed in each directory "
- "separately.", dev_dir, udev_dev_dir);
+ "separately.", dev_dir, DM_UDEV_DEV_DIR);
dm_udev_set_checking(0);
}
- udev_unref(udev);
return 1;
}
-static int _udevcreatecookie(int argc, char **argv,
- void *data __attribute__((unused)))
+static int _udevcreatecookie(CMD_ARGS)
{
uint32_t cookie;
@@ -1020,8 +1080,7 @@ static int _udevcreatecookie(int argc, char **argv,
return 1;
}
-static int _udevreleasecookie(int argc, char **argv,
- void *data __attribute__((unused)))
+static int _udevreleasecookie(CMD_ARGS)
{
if (argv[1] && !(_udev_cookie = _get_cookie_value(argv[1])))
return 0;
@@ -1034,6 +1093,7 @@ static int _udevreleasecookie(int argc, char **argv,
return dm_udev_wait(_udev_cookie);
}
+__attribute__((format(printf, 1, 2)))
static char _yes_no_prompt(const char *prompt, ...)
{
int c = 0, ret = 0;
@@ -1062,16 +1122,25 @@ static char _yes_no_prompt(const char *prompt, ...)
return ret;
}
-static int _udevcomplete_all(int argc __attribute__((unused)), char **argv __attribute__((unused)), void *data __attribute__((unused)))
+static int _udevcomplete_all(CMD_ARGS)
{
int max_id, id, sid;
struct seminfo sinfo;
struct semid_ds sdata;
int counter = 0;
+ int skipped = 0;
+ unsigned age = 0;
+ time_t t;
+
+ if (argc == 2 && (sscanf(argv[1], "%i", &age) != 1)) {
+ log_error("Failed to read age_in_minutes parameter.");
+ return 0;
+ }
if (!_switches[YES_ARG]) {
- log_warn("This operation will destroy all semaphores with keys "
+ log_warn("This operation will destroy all semaphores %s%.0d%swith keys "
"that have a prefix %" PRIu16 " (0x%" PRIx16 ").",
+ age ? "older than " : "", age, age ? " minutes " : "",
DM_COOKIE_MAGIC, DM_COOKIE_MAGIC);
if (_yes_no_prompt("Do you really want to continue? [y/n]: ") == 'n') {
@@ -1092,6 +1161,13 @@ static int _udevcomplete_all(int argc __attribute__((unused)), char **argv __att
continue;
if (sdata.sem_perm.__key >> 16 == DM_COOKIE_MAGIC) {
+ t = time(NULL);
+
+ if (sdata.sem_ctime + age * 60 > t ||
+ sdata.sem_otime + age * 60 > t) {
+ skipped++;
+ continue;
+ }
if (semctl(sid, 0, IPC_RMID, 0) < 0) {
log_error("Could not cleanup notification semaphore "
"with semid %d and cookie value "
@@ -1105,26 +1181,27 @@ static int _udevcomplete_all(int argc __attribute__((unused)), char **argv __att
}
log_print("%d semaphores with keys prefixed by "
- "%" PRIu16 " (0x%" PRIx16 ") destroyed.",
- counter, DM_COOKIE_MAGIC, DM_COOKIE_MAGIC);
+ "%" PRIu16 " (0x%" PRIx16 ") destroyed. %d skipped.",
+ counter, DM_COOKIE_MAGIC, DM_COOKIE_MAGIC, skipped);
return 1;
}
-static int _udevcookies(int argc __attribute__((unused)), char **argv __attribute__((unused)), void *data __attribute__((unused)))
+static int _udevcookies(CMD_ARGS)
{
int max_id, id, sid;
struct seminfo sinfo;
struct semid_ds sdata;
int val;
- char *time_str;
+ char otime_str[26], ctime_str[26];
+ char *otimes, *ctimes;
if ((max_id = semctl(0, 0, SEM_INFO, &sinfo)) < 0) {
log_sys_error("sem_ctl", "SEM_INFO");
return 0;
}
- printf("cookie semid value last_semop_time\n");
+ printf("Cookie Semid Value Last semop time Last change time\n");
for (id = 0; id <= max_id; id++) {
if ((sid = semctl(id, 0, SEM_STAT, &sdata)) < 0)
@@ -1139,10 +1216,14 @@ static int _udevcookies(int argc __attribute__((unused)), char **argv __attribut
continue;
}
- time_str = ctime((const time_t *) &sdata.sem_otime);
+ if ((otimes = ctime_r((const time_t *) &sdata.sem_otime, (char *)&otime_str)))
+ otime_str[strlen(otimes)-1] = '\0';
+ if ((ctimes = ctime_r((const time_t *) &sdata.sem_ctime, (char *)&ctime_str)))
+ ctime_str[strlen(ctimes)-1] = '\0';
- printf("0x%-10x %-10d %-10d %s", sdata.sem_perm.__key,
- sid, val, time_str ? time_str : "unknown\n");
+ printf("0x%-10x %-10d %-10d %s %s\n", sdata.sem_perm.__key,
+ sid, val, otimes ? : "unknown",
+ ctimes? : "unknown");
}
}
@@ -1150,7 +1231,7 @@ static int _udevcookies(int argc __attribute__((unused)), char **argv __attribut
}
#endif /* UDEV_SYNC_SUPPORT */
-static int _version(int argc __attribute__((unused)), char **argv __attribute__((unused)), void *data __attribute__((unused)))
+static int _version(CMD_ARGS)
{
char version[80];
@@ -1196,6 +1277,13 @@ static int _simple(int task, const char *name, uint32_t event_nr, int display)
if (_switches[NOLOCKFS_ARG] && !dm_task_skip_lockfs(dmt))
goto out;
+ if (_switches[CHECKS_ARG] && !dm_task_enable_checks(dmt))
+ goto out;
+
+ /* FIXME: needs to coperate with udev */
+ if (!_set_task_add_node(dmt))
+ goto out;
+
if (_switches[READAHEAD_ARG] &&
!dm_task_set_read_ahead(dmt, _int_args[READAHEAD_ARG],
_read_ahead_flags))
@@ -1205,44 +1293,48 @@ static int _simple(int task, const char *name, uint32_t event_nr, int display)
udev_flags |= DM_UDEV_DISABLE_DM_RULES_FLAG |
DM_UDEV_DISABLE_SUBSYSTEM_RULES_FLAG;
- if (_udev_cookie) {
+ if (_udev_cookie)
cookie = _udev_cookie;
- if (_udev_only)
- udev_flags |= DM_UDEV_DISABLE_LIBRARY_FALLBACK;
- }
+
+ if (_udev_only)
+ udev_flags |= DM_UDEV_DISABLE_LIBRARY_FALLBACK;
if (udev_wait_flag && !dm_task_set_cookie(dmt, &cookie, udev_flags))
goto out;
- r = dm_task_run(dmt);
+ if (_switches[RETRY_ARG] && task == DM_DEVICE_REMOVE)
+ dm_task_retry_remove(dmt);
- if (r && display && _switches[VERBOSE_ARG])
- r = _display_info(dmt);
+ r = dm_task_run(dmt);
out:
if (!_udev_cookie && udev_wait_flag)
(void) dm_udev_wait(cookie);
+ if (r && display && _switches[VERBOSE_ARG])
+ r = _display_info(dmt);
+
dm_task_destroy(dmt);
+
return r;
}
-static int _suspend(int argc, char **argv, void *data __attribute__((unused)))
+static int _suspend(CMD_ARGS)
{
return _simple(DM_DEVICE_SUSPEND, argc > 1 ? argv[1] : NULL, 0, 1);
}
-static int _resume(int argc, char **argv, void *data __attribute__((unused)))
+static int _resume(CMD_ARGS)
{
return _simple(DM_DEVICE_RESUME, argc > 1 ? argv[1] : NULL, 0, 1);
}
-static int _clear(int argc, char **argv, void *data __attribute__((unused)))
+static int _clear(CMD_ARGS)
{
return _simple(DM_DEVICE_CLEAR, argc > 1 ? argv[1] : NULL, 0, 1);
}
-static int _wait(int argc, char **argv, void *data __attribute__((unused)))
+static int _wait(CMD_ARGS)
{
const char *name = NULL;
@@ -1259,8 +1351,8 @@ static int _wait(int argc, char **argv, void *data __attribute__((unused)))
(argc > 1) ? (uint32_t) atoi(argv[argc - 1]) : 0, 1);
}
-static int _process_all(int argc, char **argv, int silent,
- int (*fn) (int argc, char **argv, void *data))
+static int _process_all(const struct command *cmd, int argc, char **argv, int silent,
+ int (*fn) (CMD_ARGS))
{
int r = 1;
struct dm_names *names;
@@ -1271,6 +1363,9 @@ static int _process_all(int argc, char **argv, int silent,
if (!(dmt = dm_task_create(DM_DEVICE_LIST)))
return 0;
+ if (_switches[CHECKS_ARG] && !dm_task_enable_checks(dmt))
+ goto out;
+
if (!dm_task_run(dmt)) {
r = 0;
goto out;
@@ -1289,7 +1384,7 @@ static int _process_all(int argc, char **argv, int silent,
do {
names = (struct dm_names *)((char *) names + next);
- if (!fn(argc, argv, names))
+ if (!fn(cmd, argc, argv, names, 1))
r = 0;
next = names->next;
} while (next);
@@ -1319,6 +1414,9 @@ static uint64_t _get_device_size(const char *name)
if (_switches[INACTIVE_ARG] && !dm_task_query_inactive_table(dmt))
goto out;
+ if (_switches[CHECKS_ARG] && !dm_task_enable_checks(dmt))
+ goto out;
+
if (!dm_task_run(dmt))
goto out;
@@ -1336,18 +1434,14 @@ static uint64_t _get_device_size(const char *name)
return size;
}
-static int _error_device(int argc __attribute__((unused)), char **argv __attribute__((unused)), void *data)
+static int _error_device(CMD_ARGS)
{
- struct dm_names *names = (struct dm_names *) data;
struct dm_task *dmt;
const char *name;
uint64_t size;
int r = 0;
- if (data)
- name = names->name;
- else
- name = argv[1];
+ name = names ? names->name : argv[1];
size = _get_device_size(name);
@@ -1369,6 +1463,9 @@ static int _error_device(int argc __attribute__((unused)), char **argv __attribu
if (_switches[INACTIVE_ARG] && !dm_task_query_inactive_table(dmt))
goto error;
+ if (_switches[CHECKS_ARG] && !dm_task_enable_checks(dmt))
+ goto error;
+
if (!dm_task_run(dmt))
goto error;
@@ -1384,22 +1481,22 @@ error:
return r;
}
-static int _remove(int argc, char **argv, void *data __attribute__((unused)))
+static int _remove(CMD_ARGS)
{
if (_switches[FORCE_ARG] && argc > 1)
- (void) _error_device(argc, argv, NULL);
+ (void) _error_device(cmd, argc, argv, NULL, 0);
return _simple(DM_DEVICE_REMOVE, argc > 1 ? argv[1] : NULL, 0, 0);
}
-static int _count_devices(int argc __attribute__((unused)), char **argv __attribute__((unused)), void *data __attribute__((unused)))
+static int _count_devices(CMD_ARGS)
{
_num_devices++;
return 1;
}
-static int _remove_all(int argc __attribute__((unused)), char **argv __attribute__((unused)), void *data __attribute__((unused)))
+static int _remove_all(CMD_ARGS)
{
int r;
@@ -1410,17 +1507,17 @@ static int _remove_all(int argc __attribute__((unused)), char **argv __attribute
return r;
_num_devices = 0;
- r |= _process_all(argc, argv, 1, _count_devices);
+ r |= _process_all(cmd, argc, argv, 1, _count_devices);
/* No devices left? */
if (!_num_devices)
return r;
- r |= _process_all(argc, argv, 1, _error_device);
+ r |= _process_all(cmd, argc, argv, 1, _error_device);
r |= _simple(DM_DEVICE_REMOVE_ALL, "", 0, 0) | dm_mknodes(NULL);
_num_devices = 0;
- r |= _process_all(argc, argv, 1, _count_devices);
+ r |= _process_all(cmd, argc, argv, 1, _count_devices);
if (!_num_devices)
return r;
@@ -1437,7 +1534,7 @@ static void _display_dev(struct dm_task *dmt, const char *name)
printf("%s\t(%u, %u)\n", name, info.major, info.minor);
}
-static int _mknodes(int argc, char **argv, void *data __attribute__((unused)))
+static int _mknodes(CMD_ARGS)
{
return dm_mknodes(argc > 1 ? argv[1] : NULL);
}
@@ -1501,7 +1598,7 @@ static int _exec_command(const char *name)
return 1;
}
-static int _status(int argc, char **argv, void *data)
+static int _status(CMD_ARGS)
{
int r = 0;
struct dm_task *dmt;
@@ -1509,31 +1606,29 @@ static int _status(int argc, char **argv, void *data)
uint64_t start, length;
char *target_type = NULL;
char *params, *c;
- int cmd;
- struct dm_names *names = (struct dm_names *) data;
+ int cmdno;
const char *name = NULL;
int matched = 0;
int ls_only = 0;
struct dm_info info;
- if (data)
+ if (names)
name = names->name;
else {
if (argc == 1 && !_switches[UUID_ARG] && !_switches[MAJOR_ARG])
- return _process_all(argc, argv, 0, _status);
- if (argc == 2)
- name = argv[1];
+ return _process_all(cmd, argc, argv, 0, _status);
+ name = argv[1];
}
- if (!strcmp(argv[0], "table"))
- cmd = DM_DEVICE_TABLE;
+ if (!strcmp(cmd->name, "table"))
+ cmdno = DM_DEVICE_TABLE;
else
- cmd = DM_DEVICE_STATUS;
+ cmdno = DM_DEVICE_STATUS;
- if (!strcmp(argv[0], "ls"))
+ if (!strcmp(cmd->name, "ls"))
ls_only = 1;
- if (!(dmt = dm_task_create(cmd)))
+ if (!(dmt = dm_task_create(cmdno)))
return 0;
if (!_set_task_device(dmt, name, 0))
@@ -1545,6 +1640,12 @@ static int _status(int argc, char **argv, void *data)
if (_switches[INACTIVE_ARG] && !dm_task_query_inactive_table(dmt))
goto out;
+ if (_switches[CHECKS_ARG] && !dm_task_enable_checks(dmt))
+ goto out;
+
+ if (_switches[NOFLUSH_ARG] && !dm_task_no_flush(dmt))
+ goto out;
+
if (!dm_task_run(dmt))
goto out;
@@ -1571,12 +1672,12 @@ static int _status(int argc, char **argv, void *data)
_switches[VERBOSE_ARG]) {
if (!matched && _switches[VERBOSE_ARG])
_display_info(dmt);
- if (data && !_switches[VERBOSE_ARG])
+ if (multiple_devices && !_switches[VERBOSE_ARG])
printf("%s: ", name);
if (target_type) {
/* Suppress encryption key */
if (!_switches[SHOWKEYS_ARG] &&
- cmd == DM_DEVICE_TABLE &&
+ cmdno == DM_DEVICE_TABLE &&
!strcmp(target_type, "crypt")) {
c = params;
while (*c && *c != ' ')
@@ -1594,7 +1695,7 @@ static int _status(int argc, char **argv, void *data)
matched = 1;
} while (next);
- if (data && _switches[VERBOSE_ARG] && matched && !ls_only)
+ if (multiple_devices && _switches[VERBOSE_ARG] && matched && !ls_only)
printf("\n");
if (matched && _switches[EXEC_ARG] && _command && !_exec_command(name))
@@ -1608,7 +1709,7 @@ static int _status(int argc, char **argv, void *data)
}
/* Show target names and their version numbers */
-static int _targets(int argc __attribute__((unused)), char **argv __attribute__((unused)), void *data __attribute__((unused)))
+static int _targets(CMD_ARGS)
{
int r = 0;
struct dm_task *dmt;
@@ -1618,6 +1719,9 @@ static int _targets(int argc __attribute__((unused)), char **argv __attribute__(
if (!(dmt = dm_task_create(DM_DEVICE_LIST_VERSIONS)))
return 0;
+ if (_switches[CHECKS_ARG] && !dm_task_enable_checks(dmt))
+ goto out;
+
if (!dm_task_run(dmt))
goto out;
@@ -1640,21 +1744,19 @@ static int _targets(int argc __attribute__((unused)), char **argv __attribute__(
return r;
}
-static int _info(int argc, char **argv, void *data)
+static int _info(CMD_ARGS)
{
int r = 0;
struct dm_task *dmt;
- struct dm_names *names = (struct dm_names *) data;
char *name = NULL;
- if (data)
+ if (names)
name = names->name;
else {
if (argc == 1 && !_switches[UUID_ARG] && !_switches[MAJOR_ARG])
- return _process_all(argc, argv, 0, _info);
- if (argc == 2)
- name = argv[1];
+ return _process_all(cmd, argc, argv, 0, _info);
+ name = argv[1];
}
if (!(dmt = dm_task_create(DM_DEVICE_INFO)))
@@ -1669,6 +1771,9 @@ static int _info(int argc, char **argv, void *data)
if (_switches[INACTIVE_ARG] && !dm_task_query_inactive_table(dmt))
goto out;
+ if (_switches[CHECKS_ARG] && !dm_task_enable_checks(dmt))
+ goto out;
+
if (!dm_task_run(dmt))
goto out;
@@ -1679,23 +1784,23 @@ static int _info(int argc, char **argv, void *data)
return r;
}
-static int _deps(int argc, char **argv, void *data)
+static int _deps(CMD_ARGS)
{
int r = 0;
uint32_t i;
struct dm_deps *deps;
struct dm_task *dmt;
struct dm_info info;
- struct dm_names *names = (struct dm_names *) data;
char *name = NULL;
+ char dev_name[PATH_MAX];
+ int major, minor;
- if (data)
+ if (names)
name = names->name;
else {
if (argc == 1 && !_switches[UUID_ARG] && !_switches[MAJOR_ARG])
- return _process_all(argc, argv, 0, _deps);
- if (argc == 2)
- name = argv[1];
+ return _process_all(cmd, argc, argv, 0, _deps);
+ name = argv[1];
}
if (!(dmt = dm_task_create(DM_DEVICE_DEPS)))
@@ -1710,6 +1815,9 @@ static int _deps(int argc, char **argv, void *data)
if (_switches[INACTIVE_ARG] && !dm_task_query_inactive_table(dmt))
goto out;
+ if (_switches[CHECKS_ARG] && !dm_task_enable_checks(dmt))
+ goto out;
+
if (!dm_task_run(dmt))
goto out;
@@ -1728,17 +1836,24 @@ static int _deps(int argc, char **argv, void *data)
if (_switches[VERBOSE_ARG])
_display_info(dmt);
- if (data && !_switches[VERBOSE_ARG])
+ if (multiple_devices && !_switches[VERBOSE_ARG])
printf("%s: ", name);
printf("%d dependencies\t:", deps->count);
- for (i = 0; i < deps->count; i++)
- printf(" (%d, %d)",
- (int) MAJOR(deps->device[i]),
- (int) MINOR(deps->device[i]));
+ for (i = 0; i < deps->count; i++) {
+ major = (int) MAJOR(deps->device[i]);
+ minor = (int) MINOR(deps->device[i]);
+
+ if ((_dev_name_type == DN_BLK || _dev_name_type == DN_MAP) &&
+ dm_device_get_name(major, minor, _dev_name_type == DN_BLK,
+ dev_name, PATH_MAX))
+ printf(" (%s)", dev_name);
+ else
+ printf(" (%d, %d)", major, minor);
+ }
printf("\n");
- if (data && _switches[VERBOSE_ARG])
+ if (multiple_devices && _switches[VERBOSE_ARG])
printf("\n");
r = 1;
@@ -1748,12 +1863,21 @@ static int _deps(int argc, char **argv, void *data)
return r;
}
-static int _display_name(int argc __attribute__((unused)), char **argv __attribute__((unused)), void *data)
+static int _display_name(CMD_ARGS)
{
- struct dm_names *names = (struct dm_names *) data;
+ char dev_name[PATH_MAX];
+
+ if (!names)
+ return 1;
- printf("%s\t(%d, %d)\n", names->name,
- (int) MAJOR(names->dev), (int) MINOR(names->dev));
+ if ((_dev_name_type == DN_BLK || _dev_name_type == DN_MAP) &&
+ dm_device_get_name((int) MAJOR(names->dev), (int) MINOR(names->dev),
+ _dev_name_type == DN_BLK, dev_name, PATH_MAX))
+ printf("%s\t(%s)\n", names->name, dev_name);
+ else
+ printf("%s\t(%d:%d)\n", names->name,
+ (int) MAJOR(names->dev),
+ (int) MINOR(names->dev));
return 1;
}
@@ -1764,6 +1888,7 @@ static int _display_name(int argc __attribute__((unused)), char **argv __attribu
enum {
TR_DEVICE=0, /* display device major:minor number */
+ TR_BLKDEVNAME, /* display device kernel name */
TR_TABLE,
TR_STATUS,
TR_ACTIVE,
@@ -1970,6 +2095,11 @@ static void _display_tree_attributes(struct dm_tree_node *node)
_out_char(']');
}
+/* FIXME Display table or status line. (Disallow both?) */
+static void _display_tree_targets(struct dm_tree_node *node, unsigned depth)
+{
+}
+
static void _display_tree_node(struct dm_tree_node *node, unsigned depth,
unsigned first_child __attribute__((unused)),
unsigned last_child, unsigned has_children)
@@ -1978,6 +2108,7 @@ static void _display_tree_node(struct dm_tree_node *node, unsigned depth,
const char *name;
const struct dm_info *info;
int first_on_line = 0;
+ char dev_name[PATH_MAX];
/* Sub-tree for targets has 2 more depth */
if (depth + 2 > MAX_DEPTH)
@@ -1985,7 +2116,8 @@ static void _display_tree_node(struct dm_tree_node *node, unsigned depth,
name = dm_tree_node_get_name(node);
- if ((!name || !*name) && !_tree_switches[TR_DEVICE])
+ if ((!name || !*name) &&
+ (!_tree_switches[TR_DEVICE] && !_tree_switches[TR_BLKDEVNAME]))
return;
/* Indicate whether there are more nodes at this depth */
@@ -2010,6 +2142,13 @@ static void _display_tree_node(struct dm_tree_node *node, unsigned depth,
info = dm_tree_node_get_info(node);
+ if (_tree_switches[TR_BLKDEVNAME] &&
+ dm_device_get_name(info->major, info->minor, 1, dev_name, PATH_MAX)) {
+ _out_string(name ? " <" : "<");
+ _out_string(dev_name);
+ _out_char('>');
+ }
+
if (_tree_switches[TR_DEVICE]) {
_out_string(name ? " (" : "(");
(void) _out_int(info->major);
@@ -2030,7 +2169,7 @@ static void _display_tree_node(struct dm_tree_node *node, unsigned depth,
if (TR_PRINT_TARGETS) {
_tree_more[depth + 1] = has_children;
- // FIXME _display_tree_targets(name, depth + 2);
+ _display_tree_targets(node, depth + 2);
}
}
@@ -2063,11 +2202,10 @@ static void _display_tree_walk_children(struct dm_tree_node *node,
}
}
-static int _add_dep(int argc __attribute__((unused)), char **argv __attribute__((unused)), void *data)
+static int _add_dep(CMD_ARGS)
{
- struct dm_names *names = (struct dm_names *) data;
-
- if (!dm_tree_add_dev(_dtree, (unsigned) MAJOR(names->dev), (unsigned) MINOR(names->dev)))
+ if (names &&
+ !dm_tree_add_dev(_dtree, (unsigned) MAJOR(names->dev), (unsigned) MINOR(names->dev)))
return 0;
return 1;
@@ -2076,7 +2214,7 @@ static int _add_dep(int argc __attribute__((unused)), char **argv __attribute__(
/*
* Create and walk dependency tree
*/
-static int _build_whole_deptree(void)
+static int _build_whole_deptree(const struct command *cmd)
{
if (_dtree)
return 1;
@@ -2084,17 +2222,15 @@ static int _build_whole_deptree(void)
if (!(_dtree = dm_tree_create()))
return 0;
- if (!_process_all(0, NULL, 0, _add_dep))
+ if (!_process_all(cmd, 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)))
+static int _display_tree(CMD_ARGS)
{
- if (!_build_whole_deptree())
+ if (!_build_whole_deptree(cmd))
return 0;
_display_tree_walk_children(dm_tree_find_node(_dtree, 0, 0), 0);
@@ -2138,6 +2274,38 @@ static int _dm_name_disp(struct dm_report *rh,
return dm_report_field_string(rh, field, &name);
}
+static int _dm_mangled_name_disp(struct dm_report *rh,
+ struct dm_pool *mem __attribute__((unused)),
+ struct dm_report_field *field, const void *data,
+ void *private __attribute__((unused)))
+{
+ char *name;
+ int r = 0;
+
+ if ((name = dm_task_get_name_mangled((const struct dm_task *) data))) {
+ r = dm_report_field_string(rh, field, (const char * const *) &name);
+ dm_free(name);
+ }
+
+ return r;
+}
+
+static int _dm_unmangled_name_disp(struct dm_report *rh,
+ struct dm_pool *mem __attribute__((unused)),
+ struct dm_report_field *field, const void *data,
+ void *private __attribute__((unused)))
+{
+ char *name;
+ int r = 0;
+
+ if ((name = dm_task_get_name_unmangled((const struct dm_task *) data))) {
+ r = dm_report_field_string(rh, field, (const char * const *) &name);
+ dm_free(name);
+ }
+
+ return r;
+}
+
static int _dm_uuid_disp(struct dm_report *rh,
struct dm_pool *mem __attribute__((unused)),
struct dm_report_field *field,
@@ -2151,6 +2319,38 @@ static int _dm_uuid_disp(struct dm_report *rh,
return dm_report_field_string(rh, field, &uuid);
}
+static int _dm_mangled_uuid_disp(struct dm_report *rh,
+ struct dm_pool *mem __attribute__((unused)),
+ struct dm_report_field *field,
+ const void *data, void *private __attribute__((unused)))
+{
+ char *uuid;
+ int r = 0;
+
+ if ((uuid = dm_task_get_uuid_mangled((const struct dm_task *) data))) {
+ r = dm_report_field_string(rh, field, (const char * const *) &uuid);
+ dm_free(uuid);
+ }
+
+ return r;
+}
+
+static int _dm_unmangled_uuid_disp(struct dm_report *rh,
+ struct dm_pool *mem __attribute__((unused)),
+ struct dm_report_field *field,
+ const void *data, void *private __attribute__((unused)))
+{
+ char *uuid;
+ int r = 0;
+
+ if ((uuid = dm_task_get_uuid_unmangled((const struct dm_task *) data))) {
+ r = dm_report_field_string(rh, field, (const char * const *) &uuid);
+ dm_free(uuid);
+ }
+
+ return r;
+}
+
static int _dm_read_ahead_disp(struct dm_report *rh,
struct dm_pool *mem __attribute__((unused)),
struct dm_report_field *field, const void *data,
@@ -2164,6 +2364,24 @@ static int _dm_read_ahead_disp(struct dm_report *rh,
return dm_report_field_uint32(rh, field, &value);
}
+static int _dm_blk_name_disp(struct dm_report *rh,
+ struct dm_pool *mem __attribute__((unused)),
+ struct dm_report_field *field, const void *data,
+ void *private __attribute__((unused)))
+{
+ char dev_name[PATH_MAX];
+ const char *s = dev_name;
+ const struct dm_info *info = data;
+
+ if (!dm_device_get_name(info->major, info->minor, 1, dev_name, PATH_MAX)) {
+ log_error("Could not resolve block device name for %d:%d.",
+ info->major, info->minor);
+ return 0;
+ }
+
+ return dm_report_field_string(rh, field, &s);
+}
+
static int _dm_info_status_disp(struct dm_report *rh,
struct dm_pool *mem __attribute__((unused)),
struct dm_report_field *field, const void *data,
@@ -2243,7 +2461,7 @@ 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;
+ char buf[PATH_MAX], *repstr;
const struct dm_info *info = data;
if (!dm_pool_begin_object(mem, 8)) {
@@ -2251,10 +2469,17 @@ static int _dm_info_devno_disp(struct dm_report *rh, struct dm_pool *mem,
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 (private) {
+ if (!dm_device_get_name(info->major, info->minor,
+ 1, buf, PATH_MAX))
+ goto out_abandon;
+ }
+ else {
+ 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)) {
@@ -2395,13 +2620,14 @@ static int _dm_tree_parents_count_disp(struct dm_report *rh,
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)
+static int _dm_deps_disp_common(struct dm_report *rh, struct dm_pool*mem,
+ struct dm_report_field *field, const void *data,
+ void *private, int disp_blk_dev_names)
{
const struct dm_deps *deps = data;
- int i;
- char buf[DM_MAX_TYPE_NAME], *repstr;
+ char buf[PATH_MAX], *repstr;
+ int major, minor;
+ unsigned i;
if (!dm_pool_begin_object(mem, 16)) {
log_error("dm_pool_begin_object failed");
@@ -2409,16 +2635,27 @@ static int _dm_deps_disp(struct dm_report *rh, struct dm_pool *mem,
}
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) {
+ major = (int) MAJOR(deps->device[i]);
+ minor = (int) MINOR(deps->device[i]);
+
+ if (disp_blk_dev_names) {
+ if (!dm_device_get_name(major, minor, 1, buf, PATH_MAX)) {
+ log_error("Could not resolve block device "
+ "name for %d:%d.", major, minor);
+ goto out_abandon;
+ }
+ }
+ else if (dm_snprintf(buf, sizeof(buf), "%d:%d",
+ major, minor) < 0) {
log_error("dm_snprintf failed");
goto out_abandon;
}
+
if (!dm_pool_grow_object(mem, buf, 0)) {
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;
@@ -2439,12 +2676,26 @@ static int _dm_deps_disp(struct dm_report *rh, struct dm_pool *mem,
return 0;
}
+static int _dm_deps_disp(struct dm_report *rh, struct dm_pool *mem,
+ struct dm_report_field *field, const void *data,
+ void *private)
+{
+ return _dm_deps_disp_common(rh, mem, field, data, private, 0);
+}
+
+static int _dm_deps_blk_names_disp(struct dm_report *rh, struct dm_pool *mem,
+ struct dm_report_field *field,
+ const void *data, void *private)
+{
+ return _dm_deps_disp_common(rh, mem, field, data, private, 1);
+}
+
static int _dm_subsystem_disp(struct dm_report *rh,
struct dm_pool *mem __attribute__((unused)),
struct dm_report_field *field, const void *data,
void *private __attribute__((unused)))
{
- return dm_report_field_string(rh, field, (const char **) data);
+ return dm_report_field_string(rh, field, (const char *const *) data);
}
static int _dm_vg_name_disp(struct dm_report *rh,
@@ -2453,7 +2704,7 @@ static int _dm_vg_name_disp(struct dm_report *rh,
void *private __attribute__((unused)))
{
- return dm_report_field_string(rh, field, (const char **) data);
+ return dm_report_field_string(rh, field, (const char *const *) data);
}
static int _dm_lv_name_disp(struct dm_report *rh,
@@ -2462,7 +2713,7 @@ static int _dm_lv_name_disp(struct dm_report *rh,
void *private __attribute__((unused)))
{
- return dm_report_field_string(rh, field, (const char **) data);
+ return dm_report_field_string(rh, field, (const char *const *) data);
}
static int _dm_lv_layer_name_disp(struct dm_report *rh,
@@ -2471,7 +2722,7 @@ static int _dm_lv_layer_name_disp(struct dm_report *rh,
void *private __attribute__((unused)))
{
- return dm_report_field_string(rh, field, (const char **) data);
+ return dm_report_field_string(rh, field, (const char *const *) data);
}
static void *_task_get_obj(void *obj)
@@ -2518,11 +2769,16 @@ static const struct dm_report_object_type _report_types[] = {
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, "MangledName", 16, dm_mangled_name, "mangled_name", "Mangled name of mapped device.")
+FIELD_F(TASK, STR, "UnmangledName", 16, dm_unmangled_name, "unmangled_name", "Unmangled name of mapped device.")
FIELD_F(TASK, STR, "UUID", 32, dm_uuid, "uuid", "Unique (optional) identifier for mapped device.")
+FIELD_F(TASK, STR, "MangledUUID", 32, dm_mangled_uuid, "mangled_uuid", "Mangled unique (optional) identifier for mapped device.")
+FIELD_F(TASK, STR, "UnmangledUUID", 32, dm_unmangled_uuid, "unmangled_uuid", "Unmangled unique (optional) identifier for mapped device.")
/* FIXME Next one should be INFO */
FIELD_F(TASK, NUM, "RAhead", 6, dm_read_ahead, "read_ahead", "Read ahead in sectors.")
+FIELD_F(INFO, STR, "BlkDevName", 16, dm_blk_name, "blkdevname", "Name of block 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, "Tables", 6, dm_info_table_loaded, "tables_loaded", "Which of the live and inactive table slots are filled.")
FIELD_F(INFO, STR, "Suspended", 9, dm_info_suspended, "suspended", "Whether the device is suspended.")
@@ -2535,8 +2791,9 @@ FIELD_O(INFO, dm_info, NUM, "Targ", target_count, 4, int32, "segments", "Number
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, STR, "DevNamesUsed", 16, dm_deps_names, "devs_used", "List of names of mapped devices used by this one.")
+FIELD_F(DEPS, STR, "DevNosUsed", 16, dm_deps, "devnos_used", "List of device numbers of devices used by this one.")
+FIELD_F(DEPS, STR, "BlkDevNamesUsed", 16, dm_deps_blk_names, "blkdevs_used", "List of names of block 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.")
@@ -2559,7 +2816,7 @@ FIELD_O(NAME, dm_split_name, STR, "LVLayer", lv_layer, 7, dm_lv_layer_name, "lv_
static const char *default_report_options = "name,major,minor,attr,open,segments,events,uuid";
static const char *splitname_report_options = "vg_name,lv_name,lv_layer";
-static int _report_init(struct command *c)
+static int _report_init(const struct command *cmd)
{
char *options = (char *) default_report_options;
const char *keys = "";
@@ -2570,7 +2827,7 @@ static int _report_init(struct command *c)
size_t len = 0;
int r = 0;
- if (c && !strcmp(c->name, "splitname"))
+ if (cmd && !strcmp(cmd->name, "splitname"))
options = (char *) splitname_report_options;
/* emulate old dmsetup behaviour */
@@ -2616,7 +2873,7 @@ static int _report_init(struct command *c)
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"))) {
+ if (cmd && (!strcmp(cmd->name, "status") || !strcmp(cmd->name, "table"))) {
err("--sort is not yet supported with status and table");
goto out;
}
@@ -2650,7 +2907,7 @@ static int _report_init(struct command *c)
options, separator, flags, keys, NULL)))
goto out;
- if ((_report_type & DR_TREE) && !_build_whole_deptree()) {
+ if ((_report_type & DR_TREE) && !_build_whole_deptree(cmd)) {
err("Internal device dependency tree creation failed.");
goto out;
}
@@ -2673,56 +2930,149 @@ out:
/*
* List devices
*/
-static int _ls(int argc, char **argv, void *data)
+static int _ls(CMD_ARGS)
{
if ((_switches[TARGET_ARG] && _target) ||
(_switches[EXEC_ARG] && _command))
- return _status(argc, argv, data);
+ return _status(cmd, argc, argv, NULL, 0);
else if ((_switches[TREE_ARG]))
- return _display_tree(argc, argv, data);
+ return _display_tree(cmd, 0, NULL, NULL, 0);
else
- return _process_all(argc, argv, 0, _display_name);
+ return _process_all(cmd, argc, argv, 0, _display_name);
}
-static int _help(int argc, char **argv, void *data);
+static int _mangle(CMD_ARGS)
+{
+ const char *name, *uuid;
+ char *new_name = NULL, *new_uuid = NULL;
+ struct dm_task *dmt;
+ struct dm_info info;
+ int r = 0;
+ int target_format;
+
+ if (names)
+ name = names->name;
+ else {
+ if (argc == 1 && !_switches[UUID_ARG] && !_switches[MAJOR_ARG])
+ return _process_all(cmd, argc, argv, 0, _mangle);
+ name = argv[1];
+ }
+
+ if (!(dmt = dm_task_create(DM_DEVICE_STATUS)))
+ return 0;
+
+ if (!(_set_task_device(dmt, name, 0)))
+ goto out;
+
+ if (!_switches[CHECKS_ARG] && !dm_task_enable_checks(dmt))
+ goto out;
+
+ if (!dm_task_run(dmt))
+ goto out;
+
+ if (!dm_task_get_info(dmt, &info) || !info.exists)
+ goto out;
+
+ uuid = dm_task_get_uuid(dmt);
+
+ target_format = _switches[MANGLENAME_ARG] ? _int_args[MANGLENAME_ARG]
+ : DEFAULT_DM_NAME_MANGLING;
+
+ if (target_format == DM_STRING_MANGLING_AUTO) {
+ if (strstr(name, "\\x5cx")) {
+ log_error("The name \"%s\" seems to be mangled more than once. "
+ "Manual intervention required to rename the device.", name);
+ goto out;
+ }
+ if (strstr(uuid, "\\x5cx")) {
+ log_error("The UUID \"%s\" seems to be mangled more than once. "
+ "Manual intervention required to correct the device UUID.", uuid);
+ goto out;
+ }
+ }
+
+ if (target_format == DM_STRING_MANGLING_NONE) {
+ if (!(new_name = dm_task_get_name_unmangled(dmt)))
+ goto out;
+ if (!(new_uuid = dm_task_get_uuid_unmangled(dmt)))
+ goto out;
+ }
+ else {
+ if (!(new_name = dm_task_get_name_mangled(dmt)))
+ goto out;
+ if (!(new_uuid = dm_task_get_uuid_mangled(dmt)))
+ goto out;
+ }
+
+ /* We can't rename the UUID, the device must be reactivated manually. */
+ if (strcmp(uuid, new_uuid)) {
+ log_error("%s: %s: UUID in incorrect form. ", name, uuid);
+ log_error("Unable to change device UUID. The device must be deactivated first.");
+ r = 0;
+ goto out;
+ }
+
+ /* Nothing to do if the name is in correct form already. */
+ if (!strcmp(name, new_name)) {
+ log_print("%s: %s: name %salready in correct form", name,
+ *uuid ? uuid : "[no UUID]", *uuid ? "and UUID " : "");
+ r = 1;
+ goto out;
+ }
+ else
+ log_print("%s: renaming to %s", name, new_name);
+
+ /* Rename to correct form of the name. */
+ r = _do_rename(name, new_name, NULL);
+
+out:
+ dm_free(new_name);
+ dm_free(new_uuid);
+ dm_task_destroy(dmt);
+ return r;
+}
+
+static int _help(CMD_ARGS);
/*
* Dispatch table
*/
static struct command _commands[] = {
- {"help", "[-c|-C|--columns]", 0, 0, _help},
+ {"help", "[-c|-C|--columns]", 0, 0, 0, _help},
{"create", "<dev_name> [-j|--major <major> -m|--minor <minor>]\n"
"\t [-U|--uid <uid>] [-G|--gid <gid>] [-M|--mode <octal_mode>]\n"
- "\t [-u|uuid <uuid>]\n"
+ "\t [-u|uuid <uuid>] [{--addnodeonresume|--addnodeoncreate}]\n"
"\t [--notable | --table <table> | <table_file>]",
- 1, 2, _create},
- {"remove", "[-f|--force] <device>", 0, 1, _remove},
- {"remove_all", "[-f|--force]", 0, 0, _remove_all},
- {"suspend", "[--noflush] <device>", 0, 1, _suspend},
- {"resume", "<device>", 0, 1, _resume},
- {"load", "<device> [<table_file>]", 0, 2, _load},
- {"clear", "<device>", 0, 1, _clear},
- {"reload", "<device> [<table_file>]", 0, 2, _load},
- {"rename", "<device> [--setuuid] <new_name_or_uuid>", 1, 2, _rename},
- {"message", "<device> <sector> <message>", 2, -1, _message},
- {"ls", "[--target <target_type>] [--exec <command>] [--tree [-o options]]", 0, 0, _ls},
- {"info", "[<device>]", 0, 1, _info},
- {"deps", "[<device>]", 0, 1, _deps},
- {"status", "[<device>] [--target <target_type>]", 0, 1, _status},
- {"table", "[<device>] [--target <target_type>] [--showkeys]", 0, 1, _status},
- {"wait", "<device> [<event_nr>]", 0, 2, _wait},
- {"mknodes", "[<device>]", 0, 1, _mknodes},
- {"udevcreatecookie", "", 0, 0, _udevcreatecookie},
- {"udevreleasecookie", "[<cookie>]", 0, 1, _udevreleasecookie},
- {"udevflags", "<cookie>", 1, 1, _udevflags},
- {"udevcomplete", "<cookie>", 1, 1, _udevcomplete},
- {"udevcomplete_all", "", 0, 0, _udevcomplete_all},
- {"udevcookies", "", 0, 0, _udevcookies},
- {"targets", "", 0, 0, _targets},
- {"version", "", 0, 0, _version},
- {"setgeometry", "<device> <cyl> <head> <sect> <start>", 5, 5, _setgeometry},
- {"splitname", "<device> [<subsystem>]", 1, 2, _splitname},
- {NULL, NULL, 0, 0, NULL}
+ 1, 2,0, _create},
+ {"remove", "[-f|--force] <device>", 0, -1, 1, _remove},
+ {"remove_all", "[-f|--force]", 0, 0, 0, _remove_all},
+ {"suspend", "[--noflush] <device>", 0, -1, 1, _suspend},
+ {"resume", "<device> [{--addnodeonresume|--addnodeoncreate}]", 0, -1, 1, _resume},
+ {"load", "<device> [<table_file>]", 0, 2, 0, _load},
+ {"clear", "<device>", 0, -1, 1, _clear},
+ {"reload", "<device> [<table_file>]", 0, 2, 0, _load},
+ {"wipe_table", "<device>", 0, -1, 1, _error_device},
+ {"rename", "<device> [--setuuid] <new_name_or_uuid>", 1, 2, 0, _rename},
+ {"message", "<device> <sector> <message>", 2, -1, 0, _message},
+ {"ls", "[--target <target_type>] [--exec <command>] [-o options] [--tree]", 0, 0, 0, _ls},
+ {"info", "[<device>]", 0, -1, 1, _info},
+ {"deps", "[-o options] [<device>]", 0, -1, 1, _deps},
+ {"status", "[<device>] [--noflush] [--target <target_type>]", 0, -1, 1, _status},
+ {"table", "[<device>] [--target <target_type>] [--showkeys]", 0, -1, 1, _status},
+ {"wait", "<device> [<event_nr>] [--noflush]", 0, 2, 0, _wait},
+ {"mknodes", "[<device>]", 0, -1, 1, _mknodes},
+ {"mangle", "[<device>]", 0, -1, 1, _mangle},
+ {"udevcreatecookie", "", 0, 0, 0, _udevcreatecookie},
+ {"udevreleasecookie", "[<cookie>]", 0, 1, 0, _udevreleasecookie},
+ {"udevflags", "<cookie>", 1, 1, 0, _udevflags},
+ {"udevcomplete", "<cookie>", 1, 1, 0, _udevcomplete},
+ {"udevcomplete_all", "<age_in_minutes>", 0, 1, 0, _udevcomplete_all},
+ {"udevcookies", "", 0, 0, 0, _udevcookies},
+ {"targets", "", 0, 0, 0, _targets},
+ {"version", "", 0, 0, 0, _version},
+ {"setgeometry", "<device> <cyl> <head> <sect> <start>", 5, 5, 0, _setgeometry},
+ {"splitname", "<device> [<subsystem>]", 1, 2, 0, _splitname},
+ {NULL, NULL, 0, 0, 0, NULL}
};
static void _usage(FILE *out)
@@ -2731,20 +3081,22 @@ static void _usage(FILE *out)
fprintf(out, "Usage:\n\n");
fprintf(out, "dmsetup [--version] [-h|--help [-c|-C|--columns]]\n"
- " [-v|--verbose [-v|--verbose ...]]\n"
+ " [--checks] [--manglename <mangling_mode>] [-v|--verbose [-v|--verbose ...]]\n"
" [-r|--readonly] [--noopencount] [--nolockfs] [--inactive]\n"
- " [--udevcookie] [--noudevrules] [--noudevsync] [-y|--yes]\n"
- " [--readahead [+]<sectors>|auto|none]\n"
+ " [--udevcookie [cookie]] [--noudevrules] [--noudevsync] [--verifyudev]\n"
+ " [-y|--yes] [--readahead [+]<sectors>|auto|none] [--retry]\n"
" [-c|-C|--columns] [-o <fields>] [-O|--sort <sort_fields>]\n"
" [--nameprefixes] [--noheadings] [--separator <separator>]\n\n");
for (i = 0; _commands[i].name; i++)
fprintf(out, "\t%s %s\n", _commands[i].name, _commands[i].help);
fprintf(out, "\n<device> may be device name or -u <uuid> or "
"-j <major> -m <minor>\n");
+ fprintf(out, "<mangling_mode> is one of 'none', 'auto' and 'hex'.\n");
fprintf(out, "<fields> are comma-separated. Use 'help -c' for list.\n");
fprintf(out, "Table_file contents may be supplied on stdin.\n");
- fprintf(out, "Tree options are: ascii, utf, vt100; compact, inverted, notrunc;\n"
- " [no]device, active, open, rw and uuid.\n");
+ fprintf(out, "Options are: devno, devname, blkdevname.\n");
+ fprintf(out, "Tree specific options are: ascii, utf, vt100; compact, inverted, notrunc;\n"
+ " blkdevname, [no]device, active, open, rw and uuid.\n");
fprintf(out, "\n");
}
@@ -2755,9 +3107,7 @@ static void _losetup_usage(FILE *out)
"[-o offset] [-f|loop_device] [file]\n\n");
}
-static int _help(int argc __attribute__((unused)),
- char **argv __attribute__((unused)),
- void *data __attribute__((unused)))
+static int _help(CMD_ARGS)
{
_usage(stderr);
@@ -2770,7 +3120,7 @@ static int _help(int argc __attribute__((unused)),
dm_report_free(_report);
_report = NULL;
}
- (void) _report_init(NULL);
+ (void) _report_init(cmd);
}
return 1;
@@ -2810,6 +3160,8 @@ static int _process_tree_options(const char *options)
;
if (!strncmp(s, "device", len))
_tree_switches[TR_DEVICE] = 1;
+ else if (!strncmp(s, "blkdevname", len))
+ _tree_switches[TR_BLKDEVNAME] = 1;
else if (!strncmp(s, "nodevice", len))
_tree_switches[TR_DEVICE] = 0;
else if (!strncmp(s, "status", len))
@@ -2865,6 +3217,8 @@ static char *_get_abspath(const char *path)
_path = canonicalize_file_name(path);
#else
/* FIXME Provide alternative */
+ log_error(INTERNAL_ERROR "Unimplemented _get_abspath.");
+ _path = NULL;
#endif
return _path;
}
@@ -2872,7 +3226,7 @@ static char *_get_abspath(const char *path)
static char *parse_loop_device_name(const char *dev, const char *dev_dir)
{
char *buf;
- char *device;
+ char *device = NULL;
if (!(buf = dm_malloc(PATH_MAX)))
return NULL;
@@ -2890,7 +3244,8 @@ static char *parse_loop_device_name(const char *dev, const char *dev_dir)
device[strlen(dev_dir)] != '/')
goto error;
- strncpy(buf, strrchr(device, '/') + 1, (size_t) PATH_MAX);
+ strncpy(buf, strrchr(device, '/') + 1, PATH_MAX - 1);
+ buf[PATH_MAX - 1] = '\0';
dm_free(device);
} else {
@@ -2904,7 +3259,9 @@ static char *parse_loop_device_name(const char *dev, const char *dev_dir)
return buf;
error:
+ dm_free(device);
dm_free(buf);
+
return NULL;
}
@@ -2952,7 +3309,8 @@ static int _loop_table(char *table, size_t tlen, char *file,
blksize = fsbuf.f_frsize;
#endif
- close(fd);
+ if (close(fd))
+ log_sys_error("close", file);
if (dm_snprintf(table, tlen, "%llu %llu loop %s %llu\n", 0ULL,
(long long unsigned)sectors, file, (long long unsigned)off) < 0)
@@ -2964,15 +3322,15 @@ static int _loop_table(char *table, size_t tlen, char *file,
return 1;
error:
- if (fd > -1)
- close(fd);
+ if (fd > -1 && close(fd))
+ log_sys_error("close", file);
+
return 0;
}
static int _process_losetup_switches(const char *base, int *argc, char ***argv,
const char *dev_dir)
{
- static int ind;
int c;
int encrypt_loop = 0, delete = 0, find = 0, show_all = 0;
char *device_name = NULL;
@@ -2987,8 +3345,8 @@ static int _process_losetup_switches(const char *base, int *argc, char ***argv,
optarg = 0;
optind = OPTIND_INIT;
- while ((ind = -1, c = GETOPTLONG_FN(*argc, *argv, "ade:fo:v",
- long_options, NULL)) != -1 ) {
+ while ((c = GETOPTLONG_FN(*argc, *argv, "ade:fo:v",
+ long_options, NULL)) != -1 ) {
if (c == ':' || c == '?')
return 0;
if (c == 'a')
@@ -3065,9 +3423,9 @@ static int _process_losetup_switches(const char *base, int *argc, char ***argv,
return 0;
}
- /* FIXME Missing free */
_table = dm_malloc(LOOP_TABLE_SIZE);
- if (!_loop_table(_table, (size_t) LOOP_TABLE_SIZE, loop_file, device_name, offset)) {
+ if (!_table ||
+ !_loop_table(_table, (size_t) LOOP_TABLE_SIZE, loop_file, device_name, offset)) {
fprintf(stderr, "Could not build device-mapper table for %s\n", (*argv)[0]);
dm_free(device_name);
return 0;
@@ -3080,21 +3438,68 @@ static int _process_losetup_switches(const char *base, int *argc, char ***argv,
return 1;
}
+static int _process_options(const char *options)
+{
+ const char *s, *end;
+ size_t len;
+
+ /* Tree options are processed separately. */
+ if (_switches[TREE_ARG])
+ return _process_tree_options(_string_args[OPTIONS_ARG]);
+
+ /* Column options are processed separately by _report_init (called later). */
+ if (_switches[COLS_ARG])
+ return 1;
+
+ /* No options specified. */
+ if (!_switches[OPTIONS_ARG])
+ return 1;
+
+ /* Set defaults. */
+ _dev_name_type = DN_DEVNO;
+
+ /* Parse. */
+ for (s = options; s && *s; s++) {
+ len = 0;
+ for (end = s; *end && *end != ','; end++, len++)
+ ;
+ if (!strncmp(s, "devno", len))
+ _dev_name_type = DN_DEVNO;
+ else if (!strncmp(s, "blkdevname", len))
+ _dev_name_type = DN_BLK;
+ else if (!strncmp(s, "devname", len))
+ _dev_name_type = DN_MAP;
+ else {
+ fprintf(stderr, "Option not recognised: %s\n", s);
+ return 0;
+ }
+
+ if (!*end)
+ break;
+ s = end;
+ }
+
+ return 1;
+}
+
static int _process_switches(int *argc, char ***argv, const char *dev_dir)
{
- char *base, *namebase, *s;
+ const char *base;
+ char *namebase, *s;
static int ind;
int c, r;
#ifdef HAVE_GETOPTLONG
static struct option long_options[] = {
{"readonly", 0, &ind, READ_ONLY},
+ {"checks", 0, &ind, CHECKS_ARG},
{"columns", 0, &ind, COLS_ARG},
{"exec", 1, &ind, EXEC_ARG},
{"force", 0, &ind, FORCE_ARG},
{"gid", 1, &ind, GID_ARG},
{"help", 0, &ind, HELP_ARG},
{"inactive", 0, &ind, INACTIVE_ARG},
+ {"manglename", 1, &ind, MANGLENAME_ARG},
{"major", 1, &ind, MAJOR_ARG},
{"minor", 1, &ind, MINOR_ARG},
{"mode", 1, &ind, MODE_ARG},
@@ -3109,6 +3514,7 @@ static int _process_switches(int *argc, char ***argv, const char *dev_dir)
{"noudevsync", 0, &ind, NOUDEVSYNC_ARG},
{"options", 1, &ind, OPTIONS_ARG},
{"readahead", 1, &ind, READAHEAD_ARG},
+ {"retry", 0, &ind, RETRY_ARG},
{"rows", 0, &ind, ROWS_ARG},
{"separator", 1, &ind, SEPARATOR_ARG},
{"setuuid", 0, &ind, SETUUID_ARG},
@@ -3122,8 +3528,11 @@ static int _process_switches(int *argc, char ***argv, const char *dev_dir)
{"unbuffered", 0, &ind, UNBUFFERED_ARG},
{"unquoted", 0, &ind, UNQUOTED_ARG},
{"verbose", 1, &ind, VERBOSE_ARG},
+ {"verifyudev", 0, &ind, VERIFYUDEV_ARG},
{"version", 0, &ind, VERSION_ARG},
{"yes", 0, &ind, YES_ARG},
+ {"addnodeonresume", 0, &ind, ADD_NODE_ON_RESUME_ARG},
+ {"addnodeoncreate", 0, &ind, ADD_NODE_ON_CREATE_ARG},
{0, 0, 0, 0}
};
#else
@@ -3137,8 +3546,11 @@ static int _process_switches(int *argc, char ***argv, const char *dev_dir)
memset(&_int_args, 0, sizeof(_int_args));
_read_ahead_flags = 0;
- namebase = strdup((*argv)[0]);
- base = basename(namebase);
+ if (!(namebase = strdup((*argv)[0]))) {
+ fprintf(stderr, "Failed to duplicate name.\n");
+ return 0;
+ }
+ base = dm_basename(namebase);
if (!strcmp(base, "devmap_name")) {
free(namebase);
@@ -3221,6 +3633,12 @@ static int _process_switches(int *argc, char ***argv, const char *dev_dir)
}
if (c == 'y' || ind == YES_ARG)
_switches[YES_ARG]++;
+ if (ind == ADD_NODE_ON_RESUME_ARG)
+ _switches[ADD_NODE_ON_RESUME_ARG]++;
+ if (ind == ADD_NODE_ON_CREATE_ARG)
+ _switches[ADD_NODE_ON_CREATE_ARG]++;
+ if (ind == CHECKS_ARG)
+ _switches[CHECKS_ARG]++;
if (ind == UDEVCOOKIE_ARG) {
_switches[UDEVCOOKIE_ARG]++;
_udev_cookie = _get_cookie_value(optarg);
@@ -3229,6 +3647,8 @@ static int _process_switches(int *argc, char ***argv, const char *dev_dir)
_switches[NOUDEVRULES_ARG]++;
if (ind == NOUDEVSYNC_ARG)
_switches[NOUDEVSYNC_ARG]++;
+ if (ind == VERIFYUDEV_ARG)
+ _switches[VERIFYUDEV_ARG]++;
if (c == 'G' || ind == GID_ARG) {
_switches[GID_ARG]++;
_int_args[GID_ARG] = atoi(optarg);
@@ -3242,32 +3662,46 @@ static int _process_switches(int *argc, char ***argv, const char *dev_dir)
/* FIXME Accept modes as per chmod */
_int_args[MODE_ARG] = (int) strtol(optarg, NULL, 8);
}
- if ((ind == EXEC_ARG)) {
+ if (ind == EXEC_ARG) {
_switches[EXEC_ARG]++;
_command = optarg;
}
- if ((ind == TARGET_ARG)) {
+ if (ind == TARGET_ARG) {
_switches[TARGET_ARG]++;
_target = optarg;
}
- if ((ind == INACTIVE_ARG))
- _switches[INACTIVE_ARG]++;
- if ((ind == NAMEPREFIXES_ARG))
+ if (ind == INACTIVE_ARG)
+ _switches[INACTIVE_ARG]++;
+ if ((ind == MANGLENAME_ARG)) {
+ _switches[MANGLENAME_ARG]++;
+ if (!strcasecmp(optarg, "none"))
+ _int_args[MANGLENAME_ARG] = DM_STRING_MANGLING_NONE;
+ else if (!strcasecmp(optarg, "auto"))
+ _int_args[MANGLENAME_ARG] = DM_STRING_MANGLING_AUTO;
+ else if (!strcasecmp(optarg, "hex"))
+ _int_args[MANGLENAME_ARG] = DM_STRING_MANGLING_HEX;
+ else {
+ log_error("Unknown name mangling mode");
+ return 0;
+ }
+ dm_set_name_mangling_mode((dm_string_mangling_t) _int_args[MANGLENAME_ARG]);
+ }
+ if (ind == NAMEPREFIXES_ARG)
_switches[NAMEPREFIXES_ARG]++;
- if ((ind == NOFLUSH_ARG))
+ if (ind == NOFLUSH_ARG)
_switches[NOFLUSH_ARG]++;
- if ((ind == NOHEADINGS_ARG))
+ if (ind == NOHEADINGS_ARG)
_switches[NOHEADINGS_ARG]++;
- if ((ind == NOLOCKFS_ARG))
+ if (ind == NOLOCKFS_ARG)
_switches[NOLOCKFS_ARG]++;
- if ((ind == NOOPENCOUNT_ARG))
+ if (ind == NOOPENCOUNT_ARG)
_switches[NOOPENCOUNT_ARG]++;
- if ((ind == READAHEAD_ARG)) {
+ if (ind == READAHEAD_ARG) {
_switches[READAHEAD_ARG]++;
if (!strcasecmp(optarg, "auto"))
_int_args[READAHEAD_ARG] = DM_READ_AHEAD_AUTO;
else if (!strcasecmp(optarg, "none"))
- _int_args[READAHEAD_ARG] = DM_READ_AHEAD_NONE;
+ _int_args[READAHEAD_ARG] = DM_READ_AHEAD_NONE;
else {
for (s = optarg; isspace(*s); s++)
;
@@ -3282,21 +3716,26 @@ static int _process_switches(int *argc, char ***argv, const char *dev_dir)
}
}
}
- if ((ind == ROWS_ARG))
+ if (ind == RETRY_ARG)
+ _switches[RETRY_ARG]++;
+ if (ind == ROWS_ARG)
_switches[ROWS_ARG]++;
- if ((ind == SETUUID_ARG))
+ if (ind == SETUUID_ARG)
_switches[SETUUID_ARG]++;
- if ((ind == SHOWKEYS_ARG))
+ if (ind == SHOWKEYS_ARG)
_switches[SHOWKEYS_ARG]++;
- if ((ind == TABLE_ARG)) {
+ if (ind == TABLE_ARG) {
_switches[TABLE_ARG]++;
- _table = optarg;
+ if (!(_table = dm_strdup(optarg))) {
+ log_error("Could not allocate memory for table string.");
+ return 0;
+ }
}
- if ((ind == TREE_ARG))
+ if (ind == TREE_ARG)
_switches[TREE_ARG]++;
- if ((ind == UNQUOTED_ARG))
+ if (ind == UNQUOTED_ARG)
_switches[UNQUOTED_ARG]++;
- if ((ind == VERSION_ARG))
+ if (ind == VERSION_ARG)
_switches[VERSION_ARG]++;
}
@@ -3310,7 +3749,7 @@ static int _process_switches(int *argc, char ***argv, const char *dev_dir)
return 0;
}
- if (_switches[TREE_ARG] && !_process_tree_options(_string_args[OPTIONS_ARG]))
+ if (!_process_options(_string_args[OPTIONS_ARG]))
return 0;
if (_switches[TABLE_ARG] && _switches[NOTABLE_ARG]) {
@@ -3318,6 +3757,11 @@ static int _process_switches(int *argc, char ***argv, const char *dev_dir)
return 0;
}
+ if (_switches[ADD_NODE_ON_RESUME_ARG] && _switches[ADD_NODE_ON_CREATE_ARG]) {
+ fprintf(stderr, "--addnodeonresume and --addnodeoncreate are incompatible.\n");
+ return 0;
+ }
+
*argv += optind;
*argc -= optind;
return 1;
@@ -3325,9 +3769,10 @@ static int _process_switches(int *argc, char ***argv, const char *dev_dir)
int main(int argc, char **argv)
{
- struct command *c;
int r = 1;
const char *dev_dir;
+ const struct command *cmd;
+ int multiple_devices;
(void) setlocale(LC_ALL, "");
@@ -3346,12 +3791,12 @@ int main(int argc, char **argv)
}
if (_switches[HELP_ARG]) {
- c = _find_command("help");
+ cmd = _find_command("help");
goto doit;
}
if (_switches[VERSION_ARG]) {
- c = _find_command("version");
+ cmd = _find_command("version");
goto doit;
}
@@ -3360,27 +3805,30 @@ int main(int argc, char **argv)
goto out;
}
- if (!(c = _find_command(argv[0]))) {
+ if (!(cmd = _find_command(argv[0]))) {
fprintf(stderr, "Unknown command\n");
_usage(stderr);
goto out;
}
- if (argc < c->min_args + 1 ||
- (c->max_args >= 0 && argc > c->max_args + 1)) {
+ if (argc < cmd->min_args + 1 ||
+ (cmd->max_args >= 0 && argc > cmd->max_args + 1)) {
fprintf(stderr, "Incorrect number of arguments\n");
_usage(stderr);
goto out;
}
- if (!_switches[COLS_ARG] && !strcmp(c->name, "splitname"))
+ if (!_switches[COLS_ARG] && !strcmp(cmd->name, "splitname"))
_switches[COLS_ARG]++;
+ if (!strcmp(cmd->name, "mangle"))
+ dm_set_name_mangling_mode(DM_STRING_MANGLING_NONE);
+
if (_switches[COLS_ARG]) {
- if (!_report_init(c))
+ if (!_report_init(cmd))
goto out;
if (!_report) {
- if (!strcmp(c->name, "info"))
+ if (!strcmp(cmd->name, "info"))
r = 0; /* info -c -o help */
goto out;
}
@@ -3392,10 +3840,14 @@ int main(int argc, char **argv)
#endif
doit:
- if (!c->fn(argc, argv, NULL)) {
- fprintf(stderr, "Command failed\n");
- goto out;
- }
+ multiple_devices = (cmd->repeatable_cmd && argc != 2 &&
+ (argc != 1 || (!_switches[UUID_ARG] && !_switches[MAJOR_ARG])));
+ do {
+ if (!cmd->fn(cmd, argc--, argv++, NULL, multiple_devices)) {
+ fprintf(stderr, "Command failed\n");
+ goto out;
+ }
+ } while (cmd->repeatable_cmd && argc > 1);
r = 0;
@@ -3408,5 +3860,7 @@ out:
if (_dtree)
dm_tree_free(_dtree);
+ dm_free(_table);
+
return r;
}