Home | History | Annotate | Line # | Download | only in tools
dmsetup.c revision 1.1.1.2
      1      1.1  haad /*	$NetBSD: dmsetup.c,v 1.1.1.2 2009/12/02 00:25:49 haad Exp $	*/
      2      1.1  haad 
      3      1.1  haad /*
      4      1.1  haad  * Copyright (C) 2001-2004 Sistina Software, Inc. All rights reserved.
      5      1.1  haad  * Copyright (C) 2004-2008 Red Hat, Inc. All rights reserved.
      6      1.1  haad  * Copyright (C) 2005-2007 NEC Corporation
      7      1.1  haad  *
      8      1.1  haad  * This file is part of the device-mapper userspace tools.
      9      1.1  haad  *
     10      1.1  haad  * It includes tree drawing code based on pstree: http://psmisc.sourceforge.net/
     11      1.1  haad  *
     12      1.1  haad  * This copyrighted material is made available to anyone wishing to use,
     13      1.1  haad  * modify, copy, or redistribute it subject to the terms and conditions
     14      1.1  haad  * of the GNU General Public License v.2.
     15      1.1  haad  *
     16      1.1  haad  * You should have received a copy of the GNU General Public License
     17      1.1  haad  * along with this program; if not, write to the Free Software Foundation,
     18      1.1  haad  * Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
     19      1.1  haad  */
     20      1.1  haad 
     21      1.1  haad #define _GNU_SOURCE
     22      1.1  haad #define _FILE_OFFSET_BITS 64
     23      1.1  haad 
     24      1.1  haad #include "configure.h"
     25      1.1  haad 
     26      1.1  haad #include "dm-logging.h"
     27      1.1  haad 
     28      1.1  haad #include <stdio.h>
     29      1.1  haad #include <stdlib.h>
     30      1.1  haad #include <string.h>
     31      1.1  haad #include <ctype.h>
     32      1.1  haad #include <dirent.h>
     33      1.1  haad #include <errno.h>
     34      1.1  haad #include <unistd.h>
     35      1.1  haad #include <libgen.h>
     36      1.1  haad #include <sys/wait.h>
     37      1.1  haad #include <unistd.h>
     38      1.1  haad #include <sys/param.h>
     39      1.1  haad #include <locale.h>
     40      1.1  haad #include <langinfo.h>
     41  1.1.1.2  haad #include <time.h>
     42      1.1  haad 
     43      1.1  haad #include <fcntl.h>
     44      1.1  haad #include <sys/stat.h>
     45      1.1  haad 
     46  1.1.1.2  haad #ifdef UDEV_SYNC_SUPPORT
     47  1.1.1.2  haad #  include <sys/types.h>
     48  1.1.1.2  haad #  include <sys/ipc.h>
     49  1.1.1.2  haad #  include <sys/sem.h>
     50  1.1.1.2  haad #endif
     51  1.1.1.2  haad 
     52      1.1  haad /* FIXME Unused so far */
     53      1.1  haad #undef HAVE_SYS_STATVFS_H
     54      1.1  haad 
     55      1.1  haad #ifdef HAVE_SYS_STATVFS_H
     56      1.1  haad #  include <sys/statvfs.h>
     57      1.1  haad #endif
     58      1.1  haad 
     59      1.1  haad #ifdef HAVE_SYS_IOCTL_H
     60      1.1  haad #  include <sys/ioctl.h>
     61      1.1  haad #endif
     62      1.1  haad 
     63      1.1  haad #if HAVE_TERMIOS_H
     64      1.1  haad #  include <termios.h>
     65      1.1  haad #endif
     66      1.1  haad 
     67      1.1  haad #ifdef HAVE_GETOPTLONG
     68      1.1  haad #  include <getopt.h>
     69      1.1  haad #  define GETOPTLONG_FN(a, b, c, d, e) getopt_long((a), (b), (c), (d), (e))
     70      1.1  haad #  define OPTIND_INIT 0
     71      1.1  haad #else
     72      1.1  haad struct option {
     73      1.1  haad };
     74      1.1  haad extern int optind;
     75      1.1  haad extern char *optarg;
     76      1.1  haad #  define GETOPTLONG_FN(a, b, c, d, e) getopt((a), (b), (c))
     77      1.1  haad #  define OPTIND_INIT 1
     78      1.1  haad #endif
     79      1.1  haad 
     80      1.1  haad #ifndef TEMP_FAILURE_RETRY
     81      1.1  haad # define TEMP_FAILURE_RETRY(expression) \
     82      1.1  haad   (__extension__                                                              \
     83      1.1  haad     ({ long int __result;                                                     \
     84      1.1  haad        do __result = (long int) (expression);                                 \
     85      1.1  haad        while (__result == -1L && errno == EINTR);                             \
     86      1.1  haad        __result; }))
     87      1.1  haad #endif
     88      1.1  haad 
     89      1.1  haad #ifdef linux
     90      1.1  haad #  include "kdev_t.h"
     91      1.1  haad #else
     92      1.1  haad #  define MAJOR(x) major((x))
     93      1.1  haad #  define MINOR(x) minor((x))
     94      1.1  haad #  define MKDEV(x,y) makedev((x),(y))
     95      1.1  haad #endif
     96      1.1  haad 
     97      1.1  haad #define LINE_SIZE 4096
     98      1.1  haad #define ARGS_MAX 256
     99      1.1  haad #define LOOP_TABLE_SIZE (PATH_MAX + 255)
    100      1.1  haad 
    101      1.1  haad #define DEFAULT_DM_DEV_DIR "/dev"
    102      1.1  haad 
    103      1.1  haad /* FIXME Should be imported */
    104      1.1  haad #ifndef DM_MAX_TYPE_NAME
    105      1.1  haad #  define DM_MAX_TYPE_NAME 16
    106      1.1  haad #endif
    107      1.1  haad 
    108      1.1  haad /* FIXME Should be elsewhere */
    109      1.1  haad #define SECTOR_SHIFT 9L
    110      1.1  haad 
    111      1.1  haad #define err(msg, x...) fprintf(stderr, msg "\n", ##x)
    112      1.1  haad 
    113      1.1  haad /*
    114      1.1  haad  * We have only very simple switches ATM.
    115      1.1  haad  */
    116      1.1  haad enum {
    117      1.1  haad 	READ_ONLY = 0,
    118      1.1  haad 	COLS_ARG,
    119      1.1  haad 	EXEC_ARG,
    120      1.1  haad 	FORCE_ARG,
    121      1.1  haad 	GID_ARG,
    122  1.1.1.2  haad 	INACTIVE_ARG,
    123      1.1  haad 	MAJOR_ARG,
    124      1.1  haad 	MINOR_ARG,
    125      1.1  haad 	MODE_ARG,
    126      1.1  haad 	NAMEPREFIXES_ARG,
    127      1.1  haad 	NOFLUSH_ARG,
    128      1.1  haad 	NOHEADINGS_ARG,
    129      1.1  haad 	NOLOCKFS_ARG,
    130      1.1  haad 	NOOPENCOUNT_ARG,
    131      1.1  haad 	NOTABLE_ARG,
    132  1.1.1.2  haad 	NOUDEVSYNC_ARG,
    133      1.1  haad 	OPTIONS_ARG,
    134      1.1  haad 	READAHEAD_ARG,
    135      1.1  haad 	ROWS_ARG,
    136      1.1  haad 	SEPARATOR_ARG,
    137      1.1  haad 	SHOWKEYS_ARG,
    138      1.1  haad 	SORT_ARG,
    139      1.1  haad 	TABLE_ARG,
    140      1.1  haad 	TARGET_ARG,
    141      1.1  haad 	TREE_ARG,
    142      1.1  haad 	UID_ARG,
    143      1.1  haad 	UNBUFFERED_ARG,
    144      1.1  haad 	UNQUOTED_ARG,
    145      1.1  haad 	UUID_ARG,
    146      1.1  haad 	VERBOSE_ARG,
    147      1.1  haad 	VERSION_ARG,
    148  1.1.1.2  haad 	YES_ARG,
    149      1.1  haad 	NUM_SWITCHES
    150      1.1  haad };
    151      1.1  haad 
    152      1.1  haad typedef enum {
    153      1.1  haad 	DR_TASK = 1,
    154      1.1  haad 	DR_INFO = 2,
    155      1.1  haad 	DR_DEPS = 4,
    156  1.1.1.2  haad 	DR_TREE = 8,	/* Complete dependency tree required */
    157  1.1.1.2  haad 	DR_NAME = 16
    158      1.1  haad } report_type_t;
    159      1.1  haad 
    160      1.1  haad static int _switches[NUM_SWITCHES];
    161      1.1  haad static int _int_args[NUM_SWITCHES];
    162      1.1  haad static char *_string_args[NUM_SWITCHES];
    163      1.1  haad static int _num_devices;
    164      1.1  haad static char *_uuid;
    165      1.1  haad static char *_table;
    166      1.1  haad static char *_target;
    167      1.1  haad static char *_command;
    168      1.1  haad static uint32_t _read_ahead_flags;
    169      1.1  haad static struct dm_tree *_dtree;
    170      1.1  haad static struct dm_report *_report;
    171      1.1  haad static report_type_t _report_type;
    172      1.1  haad 
    173      1.1  haad /*
    174      1.1  haad  * Commands
    175      1.1  haad  */
    176      1.1  haad 
    177      1.1  haad typedef int (*command_fn) (int argc, char **argv, void *data);
    178      1.1  haad 
    179      1.1  haad struct command {
    180      1.1  haad 	const char *name;
    181      1.1  haad 	const char *help;
    182      1.1  haad 	int min_args;
    183      1.1  haad 	int max_args;
    184      1.1  haad 	command_fn fn;
    185      1.1  haad };
    186      1.1  haad 
    187      1.1  haad static int _parse_line(struct dm_task *dmt, char *buffer, const char *file,
    188      1.1  haad 		       int line)
    189      1.1  haad {
    190      1.1  haad 	char ttype[LINE_SIZE], *ptr, *comment;
    191      1.1  haad 	unsigned long long start, size;
    192      1.1  haad 	int n;
    193      1.1  haad 
    194      1.1  haad 	/* trim trailing space */
    195      1.1  haad 	for (ptr = buffer + strlen(buffer) - 1; ptr >= buffer; ptr--)
    196      1.1  haad 		if (!isspace((int) *ptr))
    197      1.1  haad 			break;
    198      1.1  haad 	ptr++;
    199      1.1  haad 	*ptr = '\0';
    200      1.1  haad 
    201      1.1  haad 	/* trim leading space */
    202      1.1  haad 	for (ptr = buffer; *ptr && isspace((int) *ptr); ptr++)
    203      1.1  haad 		;
    204      1.1  haad 
    205      1.1  haad 	if (!*ptr || *ptr == '#')
    206      1.1  haad 		return 1;
    207      1.1  haad 
    208      1.1  haad 	if (sscanf(ptr, "%llu %llu %s %n",
    209      1.1  haad 		   &start, &size, ttype, &n) < 3) {
    210      1.1  haad 		err("Invalid format on line %d of table %s", line, file);
    211      1.1  haad 		return 0;
    212      1.1  haad 	}
    213      1.1  haad 
    214      1.1  haad 	ptr += n;
    215      1.1  haad 	if ((comment = strchr(ptr, (int) '#')))
    216      1.1  haad 		*comment = '\0';
    217      1.1  haad 
    218      1.1  haad 	if (!dm_task_add_target(dmt, start, size, ttype, ptr))
    219      1.1  haad 		return 0;
    220      1.1  haad 
    221      1.1  haad 	return 1;
    222      1.1  haad }
    223      1.1  haad 
    224      1.1  haad static int _parse_file(struct dm_task *dmt, const char *file)
    225      1.1  haad {
    226      1.1  haad 	char *buffer = NULL;
    227      1.1  haad 	size_t buffer_size = 0;
    228      1.1  haad 	FILE *fp;
    229      1.1  haad 	int r = 0, line = 0;
    230      1.1  haad 
    231      1.1  haad 	/* one-line table on cmdline */
    232      1.1  haad 	if (_table)
    233      1.1  haad 		return _parse_line(dmt, _table, "", ++line);
    234      1.1  haad 
    235      1.1  haad 	/* OK for empty stdin */
    236      1.1  haad 	if (file) {
    237      1.1  haad 		if (!(fp = fopen(file, "r"))) {
    238      1.1  haad 			err("Couldn't open '%s' for reading", file);
    239      1.1  haad 			return 0;
    240      1.1  haad 		}
    241      1.1  haad 	} else
    242      1.1  haad 		fp = stdin;
    243      1.1  haad 
    244      1.1  haad #ifndef HAVE_GETLINE
    245      1.1  haad 	buffer_size = LINE_SIZE;
    246      1.1  haad 	if (!(buffer = dm_malloc(buffer_size))) {
    247      1.1  haad 		err("Failed to malloc line buffer.");
    248      1.1  haad 		return 0;
    249      1.1  haad 	}
    250      1.1  haad 
    251      1.1  haad 	while (fgets(buffer, (int) buffer_size, fp))
    252      1.1  haad #else
    253      1.1  haad 	while (getline(&buffer, &buffer_size, fp) > 0)
    254      1.1  haad #endif
    255      1.1  haad 		if (!_parse_line(dmt, buffer, file ? : "on stdin", ++line))
    256      1.1  haad 			goto out;
    257      1.1  haad 
    258      1.1  haad 	r = 1;
    259      1.1  haad 
    260      1.1  haad       out:
    261      1.1  haad #ifndef HAVE_GETLINE
    262      1.1  haad 	dm_free(buffer);
    263      1.1  haad #else
    264      1.1  haad 	free(buffer);
    265      1.1  haad #endif
    266      1.1  haad 	if (file && fclose(fp))
    267      1.1  haad 		fprintf(stderr, "%s: fclose failed: %s", file, strerror(errno));
    268      1.1  haad 
    269      1.1  haad 	return r;
    270      1.1  haad }
    271      1.1  haad 
    272  1.1.1.2  haad struct dm_split_name {
    273  1.1.1.2  haad         char *subsystem;
    274  1.1.1.2  haad         char *vg_name;
    275  1.1.1.2  haad         char *lv_name;
    276  1.1.1.2  haad         char *lv_layer;
    277  1.1.1.2  haad };
    278  1.1.1.2  haad 
    279      1.1  haad struct dmsetup_report_obj {
    280      1.1  haad 	struct dm_task *task;
    281      1.1  haad 	struct dm_info *info;
    282      1.1  haad 	struct dm_task *deps_task;
    283      1.1  haad 	struct dm_tree_node *tree_node;
    284  1.1.1.2  haad 	struct dm_split_name *split_name;
    285      1.1  haad };
    286      1.1  haad 
    287      1.1  haad static struct dm_task *_get_deps_task(int major, int minor)
    288      1.1  haad {
    289      1.1  haad 	struct dm_task *dmt;
    290      1.1  haad 	struct dm_info info;
    291      1.1  haad 
    292      1.1  haad 	if (!(dmt = dm_task_create(DM_DEVICE_DEPS)))
    293      1.1  haad 		return NULL;
    294      1.1  haad 
    295      1.1  haad 	if (!dm_task_set_major(dmt, major) ||
    296      1.1  haad 	    !dm_task_set_minor(dmt, minor))
    297      1.1  haad 		goto err;
    298      1.1  haad 
    299      1.1  haad 	if (_switches[NOOPENCOUNT_ARG] && !dm_task_no_open_count(dmt))
    300      1.1  haad 		goto err;
    301      1.1  haad 
    302  1.1.1.2  haad 	if (_switches[INACTIVE_ARG] && !dm_task_query_inactive_table(dmt))
    303  1.1.1.2  haad 		goto err;
    304  1.1.1.2  haad 
    305      1.1  haad 	if (!dm_task_run(dmt))
    306      1.1  haad 		goto err;
    307      1.1  haad 
    308      1.1  haad 	if (!dm_task_get_info(dmt, &info))
    309      1.1  haad 		goto err;
    310      1.1  haad 
    311      1.1  haad 	if (!info.exists)
    312      1.1  haad 		goto err;
    313      1.1  haad 
    314      1.1  haad 	return dmt;
    315      1.1  haad 
    316      1.1  haad       err:
    317      1.1  haad 	dm_task_destroy(dmt);
    318      1.1  haad 	return NULL;
    319      1.1  haad }
    320      1.1  haad 
    321  1.1.1.2  haad static char *_extract_uuid_prefix(const char *uuid, const int separator)
    322  1.1.1.2  haad {
    323  1.1.1.2  haad 	char *ptr = NULL;
    324  1.1.1.2  haad 	char *uuid_prefix = NULL;
    325  1.1.1.2  haad 	size_t len;
    326  1.1.1.2  haad 
    327  1.1.1.2  haad 	if (uuid)
    328  1.1.1.2  haad 		ptr = strchr(uuid, separator);
    329  1.1.1.2  haad 
    330  1.1.1.2  haad 	len = ptr ? ptr - uuid : 0;
    331  1.1.1.2  haad 	if (!(uuid_prefix = dm_malloc(len + 1))) {
    332  1.1.1.2  haad 		log_error("Failed to allocate memory to extract uuid prefix.");
    333  1.1.1.2  haad 		return NULL;
    334  1.1.1.2  haad 	}
    335  1.1.1.2  haad 
    336  1.1.1.2  haad 	memcpy(uuid_prefix, uuid, len);
    337  1.1.1.2  haad 	uuid_prefix[len] = '\0';
    338  1.1.1.2  haad 
    339  1.1.1.2  haad 	return uuid_prefix;
    340  1.1.1.2  haad }
    341  1.1.1.2  haad 
    342  1.1.1.2  haad static struct dm_split_name *_get_split_name(const char *uuid, const char *name,
    343  1.1.1.2  haad 					     int separator)
    344  1.1.1.2  haad {
    345  1.1.1.2  haad 	struct dm_split_name *split_name;
    346  1.1.1.2  haad 
    347  1.1.1.2  haad 	if (!(split_name = dm_malloc(sizeof(*split_name)))) {
    348  1.1.1.2  haad 		log_error("Failed to allocate memory to split device name "
    349  1.1.1.2  haad 			  "into components.");
    350  1.1.1.2  haad 		return NULL;
    351  1.1.1.2  haad 	}
    352  1.1.1.2  haad 
    353  1.1.1.2  haad 	split_name->subsystem = _extract_uuid_prefix(uuid, separator);
    354  1.1.1.2  haad 	split_name->vg_name = split_name->lv_name =
    355  1.1.1.2  haad 	    split_name->lv_layer = (char *) "";
    356  1.1.1.2  haad 
    357  1.1.1.2  haad 	if (!strcmp(split_name->subsystem, "LVM") &&
    358  1.1.1.2  haad 	    (!(split_name->vg_name = dm_strdup(name)) ||
    359  1.1.1.2  haad 	     !dm_split_lvm_name(NULL, NULL, &split_name->vg_name,
    360  1.1.1.2  haad 			        &split_name->lv_name, &split_name->lv_layer)))
    361  1.1.1.2  haad 		log_error("Failed to allocate memory to split LVM name "
    362  1.1.1.2  haad 			  "into components.");
    363  1.1.1.2  haad 
    364  1.1.1.2  haad 	return split_name;
    365  1.1.1.2  haad }
    366  1.1.1.2  haad 
    367  1.1.1.2  haad static void _destroy_split_name(struct dm_split_name *split_name)
    368  1.1.1.2  haad {
    369  1.1.1.2  haad 	/*
    370  1.1.1.2  haad 	 * lv_name and lv_layer are allocated within the same block
    371  1.1.1.2  haad 	 * of memory as vg_name so don't need to be freed separately.
    372  1.1.1.2  haad 	 */
    373  1.1.1.2  haad 	if (!strcmp(split_name->subsystem, "LVM"))
    374  1.1.1.2  haad 		dm_free(split_name->vg_name);
    375  1.1.1.2  haad 
    376  1.1.1.2  haad 	dm_free(split_name->subsystem);
    377  1.1.1.2  haad 	dm_free(split_name);
    378  1.1.1.2  haad }
    379  1.1.1.2  haad 
    380      1.1  haad static int _display_info_cols(struct dm_task *dmt, struct dm_info *info)
    381      1.1  haad {
    382      1.1  haad 	struct dmsetup_report_obj obj;
    383      1.1  haad 	int r = 0;
    384      1.1  haad 
    385      1.1  haad 	if (!info->exists) {
    386      1.1  haad 		fprintf(stderr, "Device does not exist.\n");
    387      1.1  haad 		return 0;
    388      1.1  haad 	}
    389      1.1  haad 
    390      1.1  haad 	obj.task = dmt;
    391      1.1  haad 	obj.info = info;
    392      1.1  haad 	obj.deps_task = NULL;
    393  1.1.1.2  haad 	obj.split_name = NULL;
    394      1.1  haad 
    395      1.1  haad 	if (_report_type & DR_TREE)
    396      1.1  haad 		obj.tree_node = dm_tree_find_node(_dtree, info->major, info->minor);
    397      1.1  haad 
    398      1.1  haad 	if (_report_type & DR_DEPS)
    399      1.1  haad 		obj.deps_task = _get_deps_task(info->major, info->minor);
    400      1.1  haad 
    401  1.1.1.2  haad 	if (_report_type & DR_NAME)
    402  1.1.1.2  haad 		obj.split_name = _get_split_name(dm_task_get_uuid(dmt), dm_task_get_name(dmt), '-');
    403  1.1.1.2  haad 
    404      1.1  haad 	if (!dm_report_object(_report, &obj))
    405      1.1  haad 		goto out;
    406      1.1  haad 
    407      1.1  haad 	r = 1;
    408      1.1  haad 
    409      1.1  haad       out:
    410      1.1  haad 	if (obj.deps_task)
    411      1.1  haad 		dm_task_destroy(obj.deps_task);
    412  1.1.1.2  haad 	if (obj.split_name)
    413  1.1.1.2  haad 		_destroy_split_name(obj.split_name);
    414      1.1  haad 	return r;
    415      1.1  haad }
    416      1.1  haad 
    417      1.1  haad static void _display_info_long(struct dm_task *dmt, struct dm_info *info)
    418      1.1  haad {
    419      1.1  haad 	const char *uuid;
    420      1.1  haad 	uint32_t read_ahead;
    421      1.1  haad 
    422      1.1  haad 	if (!info->exists) {
    423      1.1  haad 		printf("Device does not exist.\n");
    424      1.1  haad 		return;
    425      1.1  haad 	}
    426      1.1  haad 
    427      1.1  haad 	printf("Name:              %s\n", dm_task_get_name(dmt));
    428      1.1  haad 
    429      1.1  haad 	printf("State:             %s%s\n",
    430      1.1  haad 	       info->suspended ? "SUSPENDED" : "ACTIVE",
    431      1.1  haad 	       info->read_only ? " (READ-ONLY)" : "");
    432      1.1  haad 
    433      1.1  haad 	/* FIXME Old value is being printed when it's being changed. */
    434      1.1  haad 	if (dm_task_get_read_ahead(dmt, &read_ahead))
    435      1.1  haad 		printf("Read Ahead:        %" PRIu32 "\n", read_ahead);
    436      1.1  haad 
    437      1.1  haad 	if (!info->live_table && !info->inactive_table)
    438      1.1  haad 		printf("Tables present:    None\n");
    439      1.1  haad 	else
    440      1.1  haad 		printf("Tables present:    %s%s%s\n",
    441      1.1  haad 		       info->live_table ? "LIVE" : "",
    442      1.1  haad 		       info->live_table && info->inactive_table ? " & " : "",
    443      1.1  haad 		       info->inactive_table ? "INACTIVE" : "");
    444      1.1  haad 
    445      1.1  haad 	if (info->open_count != -1)
    446      1.1  haad 		printf("Open count:        %d\n", info->open_count);
    447      1.1  haad 
    448      1.1  haad 	printf("Event number:      %" PRIu32 "\n", info->event_nr);
    449      1.1  haad 	printf("Major, minor:      %d, %d\n", info->major, info->minor);
    450      1.1  haad 
    451      1.1  haad 	if (info->target_count != -1)
    452      1.1  haad 		printf("Number of targets: %d\n", info->target_count);
    453      1.1  haad 
    454      1.1  haad 	if ((uuid = dm_task_get_uuid(dmt)) && *uuid)
    455      1.1  haad 		printf("UUID: %s\n", uuid);
    456      1.1  haad 
    457      1.1  haad 	printf("\n");
    458      1.1  haad }
    459      1.1  haad 
    460      1.1  haad static int _display_info(struct dm_task *dmt)
    461      1.1  haad {
    462      1.1  haad 	struct dm_info info;
    463      1.1  haad 
    464      1.1  haad 	if (!dm_task_get_info(dmt, &info))
    465      1.1  haad 		return 0;
    466      1.1  haad 
    467      1.1  haad 	if (!_switches[COLS_ARG])
    468      1.1  haad 		_display_info_long(dmt, &info);
    469      1.1  haad 	else
    470      1.1  haad 		/* FIXME return code */
    471      1.1  haad 		_display_info_cols(dmt, &info);
    472      1.1  haad 
    473      1.1  haad 	return info.exists ? 1 : 0;
    474      1.1  haad }
    475      1.1  haad 
    476      1.1  haad static int _set_task_device(struct dm_task *dmt, const char *name, int optional)
    477      1.1  haad {
    478      1.1  haad 	if (name) {
    479      1.1  haad 		if (!dm_task_set_name(dmt, name))
    480      1.1  haad 			return 0;
    481      1.1  haad 	} else if (_switches[UUID_ARG]) {
    482      1.1  haad 		if (!dm_task_set_uuid(dmt, _uuid))
    483      1.1  haad 			return 0;
    484      1.1  haad 	} else if (_switches[MAJOR_ARG] && _switches[MINOR_ARG]) {
    485      1.1  haad 		if (!dm_task_set_major(dmt, _int_args[MAJOR_ARG]) ||
    486      1.1  haad 		    !dm_task_set_minor(dmt, _int_args[MINOR_ARG]))
    487      1.1  haad 			return 0;
    488      1.1  haad 	} else if (!optional) {
    489      1.1  haad 		fprintf(stderr, "No device specified.\n");
    490      1.1  haad 		return 0;
    491      1.1  haad 	}
    492      1.1  haad 
    493      1.1  haad 	return 1;
    494      1.1  haad }
    495      1.1  haad 
    496      1.1  haad static int _load(int argc, char **argv, void *data __attribute((unused)))
    497      1.1  haad {
    498      1.1  haad 	int r = 0;
    499      1.1  haad 	struct dm_task *dmt;
    500      1.1  haad 	const char *file = NULL;
    501      1.1  haad 	const char *name = NULL;
    502      1.1  haad 
    503      1.1  haad 	if (_switches[NOTABLE_ARG]) {
    504      1.1  haad 		err("--notable only available when creating new device\n");
    505      1.1  haad 		return 0;
    506      1.1  haad 	}
    507      1.1  haad 
    508      1.1  haad 	if (!_switches[UUID_ARG] && !_switches[MAJOR_ARG]) {
    509      1.1  haad 		if (argc == 1) {
    510      1.1  haad 			err("Please specify device.\n");
    511      1.1  haad 			return 0;
    512      1.1  haad 		}
    513      1.1  haad 		name = argv[1];
    514      1.1  haad 		argc--;
    515      1.1  haad 		argv++;
    516      1.1  haad 	} else if (argc > 2) {
    517      1.1  haad 		err("Too many command line arguments.\n");
    518      1.1  haad 		return 0;
    519      1.1  haad 	}
    520      1.1  haad 
    521      1.1  haad 	if (argc == 2)
    522      1.1  haad 		file = argv[1];
    523      1.1  haad 
    524      1.1  haad 	if (!(dmt = dm_task_create(DM_DEVICE_RELOAD)))
    525      1.1  haad 		return 0;
    526      1.1  haad 
    527      1.1  haad 	if (!_set_task_device(dmt, name, 0))
    528      1.1  haad 		goto out;
    529      1.1  haad 
    530      1.1  haad 	if (!_switches[NOTABLE_ARG] && !_parse_file(dmt, file))
    531      1.1  haad 		goto out;
    532      1.1  haad 
    533      1.1  haad 	if (_switches[READ_ONLY] && !dm_task_set_ro(dmt))
    534      1.1  haad 		goto out;
    535      1.1  haad 
    536      1.1  haad 	if (_switches[NOOPENCOUNT_ARG] && !dm_task_no_open_count(dmt))
    537      1.1  haad 		goto out;
    538      1.1  haad 
    539  1.1.1.2  haad 	if (_switches[INACTIVE_ARG] && !dm_task_query_inactive_table(dmt))
    540  1.1.1.2  haad 		goto out;
    541  1.1.1.2  haad 
    542      1.1  haad 	if (!dm_task_run(dmt))
    543      1.1  haad 		goto out;
    544      1.1  haad 
    545      1.1  haad 	r = 1;
    546      1.1  haad 
    547      1.1  haad 	if (_switches[VERBOSE_ARG])
    548      1.1  haad 		r = _display_info(dmt);
    549      1.1  haad 
    550      1.1  haad       out:
    551      1.1  haad 	dm_task_destroy(dmt);
    552      1.1  haad 
    553      1.1  haad 	return r;
    554      1.1  haad }
    555      1.1  haad 
    556      1.1  haad static int _create(int argc, char **argv, void *data __attribute((unused)))
    557      1.1  haad {
    558      1.1  haad 	int r = 0;
    559      1.1  haad 	struct dm_task *dmt;
    560      1.1  haad 	const char *file = NULL;
    561  1.1.1.2  haad 	uint32_t cookie = 0;
    562      1.1  haad 
    563      1.1  haad 	if (argc == 3)
    564      1.1  haad 		file = argv[2];
    565      1.1  haad 
    566      1.1  haad 	if (!(dmt = dm_task_create(DM_DEVICE_CREATE)))
    567      1.1  haad 		return 0;
    568      1.1  haad 
    569      1.1  haad 	if (!dm_task_set_name(dmt, argv[1]))
    570      1.1  haad 		goto out;
    571      1.1  haad 
    572      1.1  haad 	if (_switches[UUID_ARG] && !dm_task_set_uuid(dmt, _uuid))
    573      1.1  haad 		goto out;
    574      1.1  haad 
    575      1.1  haad 	if (!_switches[NOTABLE_ARG] && !_parse_file(dmt, file))
    576      1.1  haad 		goto out;
    577      1.1  haad 
    578      1.1  haad 	if (_switches[READ_ONLY] && !dm_task_set_ro(dmt))
    579      1.1  haad 		goto out;
    580      1.1  haad 
    581      1.1  haad 	if (_switches[MAJOR_ARG] && !dm_task_set_major(dmt, _int_args[MAJOR_ARG]))
    582      1.1  haad 		goto out;
    583      1.1  haad 
    584      1.1  haad 	if (_switches[MINOR_ARG] && !dm_task_set_minor(dmt, _int_args[MINOR_ARG]))
    585      1.1  haad 		goto out;
    586      1.1  haad 
    587      1.1  haad 	if (_switches[UID_ARG] && !dm_task_set_uid(dmt, _int_args[UID_ARG]))
    588      1.1  haad 		goto out;
    589      1.1  haad 
    590      1.1  haad 	if (_switches[GID_ARG] && !dm_task_set_gid(dmt, _int_args[GID_ARG]))
    591      1.1  haad 		goto out;
    592      1.1  haad 
    593      1.1  haad 	if (_switches[MODE_ARG] && !dm_task_set_mode(dmt, _int_args[MODE_ARG]))
    594      1.1  haad 		goto out;
    595      1.1  haad 
    596      1.1  haad 	if (_switches[NOOPENCOUNT_ARG] && !dm_task_no_open_count(dmt))
    597      1.1  haad 		goto out;
    598      1.1  haad 
    599  1.1.1.2  haad 	if (_switches[INACTIVE_ARG] && !dm_task_query_inactive_table(dmt))
    600  1.1.1.2  haad 		goto out;
    601  1.1.1.2  haad 
    602      1.1  haad 	if (_switches[READAHEAD_ARG] &&
    603      1.1  haad 	    !dm_task_set_read_ahead(dmt, _int_args[READAHEAD_ARG],
    604      1.1  haad 				    _read_ahead_flags))
    605      1.1  haad 		goto out;
    606      1.1  haad 
    607  1.1.1.2  haad 	if (_switches[NOTABLE_ARG])
    608  1.1.1.2  haad 		dm_udev_set_sync_support(0);
    609  1.1.1.2  haad 
    610  1.1.1.2  haad 	if (!dm_task_set_cookie(dmt, &cookie, 0) ||
    611  1.1.1.2  haad 	    !dm_task_run(dmt))
    612      1.1  haad 		goto out;
    613      1.1  haad 
    614      1.1  haad 	r = 1;
    615      1.1  haad 
    616      1.1  haad 	if (_switches[VERBOSE_ARG])
    617      1.1  haad 		r = _display_info(dmt);
    618      1.1  haad 
    619      1.1  haad       out:
    620  1.1.1.2  haad 	(void) dm_udev_wait(cookie);
    621      1.1  haad 	dm_task_destroy(dmt);
    622      1.1  haad 
    623      1.1  haad 	return r;
    624      1.1  haad }
    625      1.1  haad 
    626      1.1  haad static int _rename(int argc, char **argv, void *data __attribute((unused)))
    627      1.1  haad {
    628      1.1  haad 	int r = 0;
    629      1.1  haad 	struct dm_task *dmt;
    630  1.1.1.2  haad 	uint32_t cookie = 0;
    631      1.1  haad 
    632      1.1  haad 	if (!(dmt = dm_task_create(DM_DEVICE_RENAME)))
    633      1.1  haad 		return 0;
    634      1.1  haad 
    635      1.1  haad 	/* FIXME Kernel doesn't support uuid or device number here yet */
    636      1.1  haad 	if (!_set_task_device(dmt, (argc == 3) ? argv[1] : NULL, 0))
    637      1.1  haad 		goto out;
    638      1.1  haad 
    639      1.1  haad 	if (!dm_task_set_newname(dmt, argv[argc - 1]))
    640      1.1  haad 		goto out;
    641      1.1  haad 
    642      1.1  haad 	if (_switches[NOOPENCOUNT_ARG] && !dm_task_no_open_count(dmt))
    643      1.1  haad 		goto out;
    644      1.1  haad 
    645  1.1.1.2  haad 	if (_switches[INACTIVE_ARG] && !dm_task_query_inactive_table(dmt))
    646  1.1.1.2  haad 		goto out;
    647  1.1.1.2  haad 
    648  1.1.1.2  haad 	if (!dm_task_set_cookie(dmt, &cookie, 0) ||
    649  1.1.1.2  haad 	    !dm_task_run(dmt))
    650      1.1  haad 		goto out;
    651      1.1  haad 
    652      1.1  haad 	r = 1;
    653      1.1  haad 
    654      1.1  haad       out:
    655  1.1.1.2  haad 	(void) dm_udev_wait(cookie);
    656      1.1  haad 	dm_task_destroy(dmt);
    657      1.1  haad 
    658      1.1  haad 	return r;
    659      1.1  haad }
    660      1.1  haad 
    661      1.1  haad static int _message(int argc, char **argv, void *data __attribute((unused)))
    662      1.1  haad {
    663      1.1  haad 	int r = 0, i;
    664      1.1  haad 	size_t sz = 1;
    665      1.1  haad 	struct dm_task *dmt;
    666      1.1  haad 	char *str;
    667      1.1  haad 
    668      1.1  haad 	if (!(dmt = dm_task_create(DM_DEVICE_TARGET_MSG)))
    669      1.1  haad 		return 0;
    670      1.1  haad 
    671      1.1  haad 	if (_switches[UUID_ARG] || _switches[MAJOR_ARG]) {
    672      1.1  haad 		if (!_set_task_device(dmt, NULL, 0))
    673      1.1  haad 			goto out;
    674      1.1  haad 	} else {
    675      1.1  haad 		if (!_set_task_device(dmt, argv[1], 0))
    676      1.1  haad 			goto out;
    677      1.1  haad 		argc--;
    678      1.1  haad 		argv++;
    679      1.1  haad 	}
    680      1.1  haad 
    681      1.1  haad 	if (!dm_task_set_sector(dmt, (uint64_t) atoll(argv[1])))
    682      1.1  haad 		goto out;
    683      1.1  haad 
    684      1.1  haad 	argc -= 2;
    685      1.1  haad 	argv += 2;
    686      1.1  haad 
    687      1.1  haad 	if (argc <= 0)
    688      1.1  haad 		err("No message supplied.\n");
    689      1.1  haad 
    690      1.1  haad 	for (i = 0; i < argc; i++)
    691      1.1  haad 		sz += strlen(argv[i]) + 1;
    692      1.1  haad 
    693      1.1  haad 	if (!(str = dm_malloc(sz))) {
    694      1.1  haad 		err("message string allocation failed");
    695      1.1  haad 		goto out;
    696      1.1  haad 	}
    697      1.1  haad 
    698      1.1  haad 	memset(str, 0, sz);
    699      1.1  haad 
    700      1.1  haad 	for (i = 0; i < argc; i++) {
    701      1.1  haad 		if (i)
    702      1.1  haad 			strcat(str, " ");
    703      1.1  haad 		strcat(str, argv[i]);
    704      1.1  haad 	}
    705      1.1  haad 
    706      1.1  haad 	if (!dm_task_set_message(dmt, str))
    707      1.1  haad 		goto out;
    708      1.1  haad 
    709      1.1  haad 	dm_free(str);
    710      1.1  haad 
    711      1.1  haad 	if (_switches[NOOPENCOUNT_ARG] && !dm_task_no_open_count(dmt))
    712      1.1  haad 		goto out;
    713      1.1  haad 
    714  1.1.1.2  haad 	if (_switches[INACTIVE_ARG] && !dm_task_query_inactive_table(dmt))
    715  1.1.1.2  haad 		goto out;
    716  1.1.1.2  haad 
    717      1.1  haad 	if (!dm_task_run(dmt))
    718      1.1  haad 		goto out;
    719      1.1  haad 
    720      1.1  haad 	r = 1;
    721      1.1  haad 
    722      1.1  haad       out:
    723      1.1  haad 	dm_task_destroy(dmt);
    724      1.1  haad 
    725      1.1  haad 	return r;
    726      1.1  haad }
    727      1.1  haad 
    728      1.1  haad static int _setgeometry(int argc, char **argv, void *data __attribute((unused)))
    729      1.1  haad {
    730      1.1  haad 	int r = 0;
    731      1.1  haad 	struct dm_task *dmt;
    732      1.1  haad 
    733      1.1  haad 	if (!(dmt = dm_task_create(DM_DEVICE_SET_GEOMETRY)))
    734      1.1  haad 		return 0;
    735      1.1  haad 
    736      1.1  haad 	if (_switches[UUID_ARG] || _switches[MAJOR_ARG]) {
    737      1.1  haad 		if (!_set_task_device(dmt, NULL, 0))
    738      1.1  haad 			goto out;
    739      1.1  haad 	} else {
    740      1.1  haad 		if (!_set_task_device(dmt, argv[1], 0))
    741      1.1  haad 			goto out;
    742      1.1  haad 		argc--;
    743      1.1  haad 		argv++;
    744      1.1  haad 	}
    745      1.1  haad 
    746      1.1  haad 	if (!dm_task_set_geometry(dmt, argv[1], argv[2], argv[3], argv[4]))
    747      1.1  haad 		goto out;
    748      1.1  haad 
    749  1.1.1.2  haad 	if (_switches[NOOPENCOUNT_ARG] && !dm_task_no_open_count(dmt))
    750  1.1.1.2  haad 		goto out;
    751  1.1.1.2  haad 
    752  1.1.1.2  haad 	if (_switches[INACTIVE_ARG] && !dm_task_query_inactive_table(dmt))
    753  1.1.1.2  haad 		goto out;
    754  1.1.1.2  haad 
    755      1.1  haad 	/* run the task */
    756      1.1  haad 	if (!dm_task_run(dmt))
    757      1.1  haad 		goto out;
    758      1.1  haad 
    759      1.1  haad 	r = 1;
    760      1.1  haad 
    761      1.1  haad       out:
    762      1.1  haad 	dm_task_destroy(dmt);
    763      1.1  haad 
    764      1.1  haad 	return r;
    765      1.1  haad }
    766      1.1  haad 
    767  1.1.1.2  haad static int _splitname(int argc, char **argv, void *data __attribute((unused)))
    768  1.1.1.2  haad {
    769  1.1.1.2  haad 	struct dmsetup_report_obj obj;
    770  1.1.1.2  haad 	int r = 1;
    771  1.1.1.2  haad 
    772  1.1.1.2  haad 	obj.task = NULL;
    773  1.1.1.2  haad 	obj.info = NULL;
    774  1.1.1.2  haad 	obj.deps_task = NULL;
    775  1.1.1.2  haad 	obj.tree_node = NULL;
    776  1.1.1.2  haad 	obj.split_name = _get_split_name((argc == 3) ? argv[2] : "LVM",
    777  1.1.1.2  haad 					 argv[1], '\0');
    778  1.1.1.2  haad 
    779  1.1.1.2  haad 	r = dm_report_object(_report, &obj);
    780  1.1.1.2  haad 	_destroy_split_name(obj.split_name);
    781  1.1.1.2  haad 
    782  1.1.1.2  haad 	return r;
    783  1.1.1.2  haad }
    784  1.1.1.2  haad 
    785  1.1.1.2  haad static uint32_t _get_cookie_value(char *str_value)
    786  1.1.1.2  haad {
    787  1.1.1.2  haad 	unsigned long int value;
    788  1.1.1.2  haad 	char *p;
    789  1.1.1.2  haad 
    790  1.1.1.2  haad 	if (!(value = strtoul(str_value, &p, 0)) ||
    791  1.1.1.2  haad 	    *p ||
    792  1.1.1.2  haad 	    (value == ULONG_MAX && errno == ERANGE) ||
    793  1.1.1.2  haad 	    value > 0xFFFFFFFF) {
    794  1.1.1.2  haad 		err("Incorrect cookie value");
    795  1.1.1.2  haad 		return 0;
    796  1.1.1.2  haad 	}
    797  1.1.1.2  haad 	else
    798  1.1.1.2  haad 		return (uint32_t) value;
    799  1.1.1.2  haad }
    800  1.1.1.2  haad 
    801  1.1.1.2  haad static int _udevflags(int args, char **argv, void *data __attribute((unused)))
    802  1.1.1.2  haad {
    803  1.1.1.2  haad 	uint32_t cookie;
    804  1.1.1.2  haad 	uint16_t flags;
    805  1.1.1.2  haad 	int i;
    806  1.1.1.2  haad 	static const char *dm_flag_names[] = {"DISABLE_DM_RULES",
    807  1.1.1.2  haad 					      "DISABLE_SUBSYSTEM_RULES",
    808  1.1.1.2  haad 					      "DISABLE_DISK_RULES",
    809  1.1.1.2  haad 					      "DISABLE_OTHER_RULES",
    810  1.1.1.2  haad 					      "LOW_PRIORITY",
    811  1.1.1.2  haad 					       0, 0, 0};
    812  1.1.1.2  haad 
    813  1.1.1.2  haad 	if (!(cookie = _get_cookie_value(argv[1])))
    814  1.1.1.2  haad 		return 0;
    815  1.1.1.2  haad 
    816  1.1.1.2  haad 	flags = cookie >> DM_UDEV_FLAGS_SHIFT;
    817  1.1.1.2  haad 
    818  1.1.1.2  haad 	for (i = 0; i < DM_UDEV_FLAGS_SHIFT; i++)
    819  1.1.1.2  haad 		if (1 << i & flags) {
    820  1.1.1.2  haad 			if (i < DM_UDEV_FLAGS_SHIFT / 2 && dm_flag_names[i])
    821  1.1.1.2  haad 				printf("DM_UDEV_%s_FLAG='1'\n", dm_flag_names[i]);
    822  1.1.1.2  haad 			else if (i < DM_UDEV_FLAGS_SHIFT / 2)
    823  1.1.1.2  haad 				/*
    824  1.1.1.2  haad 				 * This is just a fallback. Each new DM flag
    825  1.1.1.2  haad 				 * should have its symbolic name assigned.
    826  1.1.1.2  haad 				 */
    827  1.1.1.2  haad 				printf("DM_UDEV_FLAG%d='1'\n", i);
    828  1.1.1.2  haad 			else
    829  1.1.1.2  haad 				/*
    830  1.1.1.2  haad 				 * We can't assign symbolic names to subsystem
    831  1.1.1.2  haad 				 * flags. Their semantics vary based on the
    832  1.1.1.2  haad 				 * subsystem that is currently used.
    833  1.1.1.2  haad 				 */
    834  1.1.1.2  haad 				printf("DM_SUBSYSTEM_UDEV_FLAG%d='1'\n",
    835  1.1.1.2  haad 					i - DM_UDEV_FLAGS_SHIFT / 2);
    836  1.1.1.2  haad 		}
    837  1.1.1.2  haad 
    838  1.1.1.2  haad 	return 1;
    839  1.1.1.2  haad }
    840  1.1.1.2  haad 
    841  1.1.1.2  haad static int _udevcomplete(int argc, char **argv, void *data __attribute((unused)))
    842  1.1.1.2  haad {
    843  1.1.1.2  haad 	uint32_t cookie;
    844  1.1.1.2  haad 
    845  1.1.1.2  haad 	if (!(cookie = _get_cookie_value(argv[1])))
    846  1.1.1.2  haad 		return 0;
    847  1.1.1.2  haad 
    848  1.1.1.2  haad 	/*
    849  1.1.1.2  haad 	 * Strip flags from the cookie and use cookie magic instead.
    850  1.1.1.2  haad 	 * If the cookie has non-zero prefix and the base is zero then
    851  1.1.1.2  haad 	 * this one carries flags to control udev rules only and it is
    852  1.1.1.2  haad 	 * not meant to be for notification. Return with success in this
    853  1.1.1.2  haad 	 * situation.
    854  1.1.1.2  haad 	 */
    855  1.1.1.2  haad 	if (!(cookie &= ~DM_UDEV_FLAGS_MASK))
    856  1.1.1.2  haad 		return 1;
    857  1.1.1.2  haad 
    858  1.1.1.2  haad 	cookie |= DM_COOKIE_MAGIC << DM_UDEV_FLAGS_SHIFT;
    859  1.1.1.2  haad 
    860  1.1.1.2  haad 	return dm_udev_complete(cookie);
    861  1.1.1.2  haad }
    862  1.1.1.2  haad 
    863  1.1.1.2  haad #ifndef UDEV_SYNC_SUPPORT
    864  1.1.1.2  haad static const char _cmd_not_supported[] = "Command not supported. Recompile with \"--enable-udev-sync\" to enable.";
    865  1.1.1.2  haad 
    866  1.1.1.2  haad static int _udevcomplete_all(int argc __attribute((unused)), char **argv __attribute((unused)), void *data __attribute((unused)))
    867  1.1.1.2  haad {
    868  1.1.1.2  haad 	log_error(_cmd_not_supported);
    869  1.1.1.2  haad 
    870  1.1.1.2  haad 	return 0;
    871  1.1.1.2  haad }
    872  1.1.1.2  haad 
    873  1.1.1.2  haad static int _udevcookies(int argc __attribute((unused)), char **argv __attribute((unused)), void *data __attribute((unused)))
    874  1.1.1.2  haad {
    875  1.1.1.2  haad 	log_error(_cmd_not_supported);
    876  1.1.1.2  haad 
    877  1.1.1.2  haad 	return 0;
    878  1.1.1.2  haad }
    879  1.1.1.2  haad 
    880  1.1.1.2  haad #else	/* UDEV_SYNC_SUPPORT */
    881  1.1.1.2  haad 
    882  1.1.1.2  haad static char _yes_no_prompt(const char *prompt, ...)
    883  1.1.1.2  haad {
    884  1.1.1.2  haad 	int c = 0, ret = 0;
    885  1.1.1.2  haad 	va_list ap;
    886  1.1.1.2  haad 
    887  1.1.1.2  haad 	do {
    888  1.1.1.2  haad 		if (c == '\n' || !c) {
    889  1.1.1.2  haad 			va_start(ap, prompt);
    890  1.1.1.2  haad 			vprintf(prompt, ap);
    891  1.1.1.2  haad 			va_end(ap);
    892  1.1.1.2  haad 		}
    893  1.1.1.2  haad 
    894  1.1.1.2  haad 		if ((c = getchar()) == EOF) {
    895  1.1.1.2  haad 			ret = 'n';
    896  1.1.1.2  haad 			break;
    897  1.1.1.2  haad 		}
    898  1.1.1.2  haad 
    899  1.1.1.2  haad 		c = tolower(c);
    900  1.1.1.2  haad 		if ((c == 'y') || (c == 'n'))
    901  1.1.1.2  haad 			ret = c;
    902  1.1.1.2  haad 	} while (!ret || c != '\n');
    903  1.1.1.2  haad 
    904  1.1.1.2  haad 	if (c != '\n')
    905  1.1.1.2  haad 		printf("\n");
    906  1.1.1.2  haad 
    907  1.1.1.2  haad 	return ret;
    908  1.1.1.2  haad }
    909  1.1.1.2  haad 
    910  1.1.1.2  haad static int _udevcomplete_all(int argc __attribute((unused)), char **argv __attribute((unused)), void *data __attribute((unused)))
    911  1.1.1.2  haad {
    912  1.1.1.2  haad 	int max_id, id, sid;
    913  1.1.1.2  haad 	struct seminfo sinfo;
    914  1.1.1.2  haad 	struct semid_ds sdata;
    915  1.1.1.2  haad 	int counter = 0;
    916  1.1.1.2  haad 
    917  1.1.1.2  haad 	if (!_switches[YES_ARG]) {
    918  1.1.1.2  haad 		log_warn("This operation will destroy all semaphores with keys "
    919  1.1.1.2  haad 			 "that have a prefix %" PRIu16 " (0x%" PRIx16 ").",
    920  1.1.1.2  haad 			 DM_COOKIE_MAGIC, DM_COOKIE_MAGIC);
    921  1.1.1.2  haad 
    922  1.1.1.2  haad 		if (_yes_no_prompt("Do you really want to continue? [y/n]: ") == 'n') {
    923  1.1.1.2  haad 			log_print("Semaphores with keys prefixed by %" PRIu16
    924  1.1.1.2  haad 				  " (0x%" PRIx16 ") NOT destroyed.",
    925  1.1.1.2  haad 				  DM_COOKIE_MAGIC, DM_COOKIE_MAGIC);
    926  1.1.1.2  haad 			return 1;
    927  1.1.1.2  haad 		}
    928  1.1.1.2  haad 	}
    929  1.1.1.2  haad 
    930  1.1.1.2  haad 	if ((max_id = semctl(0, 0, SEM_INFO, &sinfo)) < 0) {
    931  1.1.1.2  haad 		log_sys_error("semctl", "SEM_INFO");
    932  1.1.1.2  haad 		return 0;
    933  1.1.1.2  haad 	}
    934  1.1.1.2  haad 
    935  1.1.1.2  haad 	for (id = 0; id <= max_id; id++) {
    936  1.1.1.2  haad 		if ((sid = semctl(id, 0, SEM_STAT, &sdata)) < 0)
    937  1.1.1.2  haad 			continue;
    938  1.1.1.2  haad 
    939  1.1.1.2  haad 		if (sdata.sem_perm.__key >> 16 == DM_COOKIE_MAGIC) {
    940  1.1.1.2  haad 			if (semctl(sid, 0, IPC_RMID, 0) < 0) {
    941  1.1.1.2  haad 				log_error("Could not cleanup notification semaphore "
    942  1.1.1.2  haad 					  "with semid %d and cookie value "
    943  1.1.1.2  haad 					  "%" PRIu32 " (0x%" PRIx32 ")", sid,
    944  1.1.1.2  haad 					  sdata.sem_perm.__key, sdata.sem_perm.__key);
    945  1.1.1.2  haad 				continue;
    946  1.1.1.2  haad 			}
    947  1.1.1.2  haad 
    948  1.1.1.2  haad 			counter++;
    949  1.1.1.2  haad 		}
    950  1.1.1.2  haad 	}
    951  1.1.1.2  haad 
    952  1.1.1.2  haad 	log_print("%d semaphores with keys prefixed by "
    953  1.1.1.2  haad 		  "%" PRIu16 " (0x%" PRIx16 ") destroyed.",
    954  1.1.1.2  haad 		  counter, DM_COOKIE_MAGIC, DM_COOKIE_MAGIC);
    955  1.1.1.2  haad 
    956  1.1.1.2  haad 	return 1;
    957  1.1.1.2  haad }
    958  1.1.1.2  haad 
    959  1.1.1.2  haad static int _udevcookies(int argc __attribute((unused)), char **argv __attribute((unused)), void *data __attribute((unused)))
    960  1.1.1.2  haad {
    961  1.1.1.2  haad 	int max_id, id, sid;
    962  1.1.1.2  haad 	struct seminfo sinfo;
    963  1.1.1.2  haad 	struct semid_ds sdata;
    964  1.1.1.2  haad 	int val;
    965  1.1.1.2  haad 	char *time_str;
    966  1.1.1.2  haad 
    967  1.1.1.2  haad 	if ((max_id = semctl(0, 0, SEM_INFO, &sinfo)) < 0) {
    968  1.1.1.2  haad 		log_sys_error("sem_ctl", "SEM_INFO");
    969  1.1.1.2  haad 		return 0;
    970  1.1.1.2  haad 	}
    971  1.1.1.2  haad 
    972  1.1.1.2  haad 	printf("cookie       semid      value      last_semop_time\n");
    973  1.1.1.2  haad 
    974  1.1.1.2  haad 	for (id = 0; id <= max_id; id++) {
    975  1.1.1.2  haad 		if ((sid = semctl(id, 0, SEM_STAT, &sdata)) < 0)
    976  1.1.1.2  haad 			continue;
    977  1.1.1.2  haad 
    978  1.1.1.2  haad 		if (sdata.sem_perm.__key >> 16 == DM_COOKIE_MAGIC) {
    979  1.1.1.2  haad 			if ((val = semctl(sid, 0, GETVAL)) < 0) {
    980  1.1.1.2  haad 				log_error("semid %d: sem_ctl failed for "
    981  1.1.1.2  haad 					  "cookie 0x%" PRIx32 ": %s",
    982  1.1.1.2  haad 					  sid, sdata.sem_perm.__key,
    983  1.1.1.2  haad 					  strerror(errno));
    984  1.1.1.2  haad 				continue;
    985  1.1.1.2  haad 			}
    986  1.1.1.2  haad 
    987  1.1.1.2  haad 			time_str = ctime((const time_t *) &sdata.sem_otime);
    988  1.1.1.2  haad 
    989  1.1.1.2  haad 			printf("0x%-10x %-10d %-10d %s", sdata.sem_perm.__key,
    990  1.1.1.2  haad 				sid, val, time_str ? time_str : "unknown\n");
    991  1.1.1.2  haad 		}
    992  1.1.1.2  haad 	}
    993  1.1.1.2  haad 
    994  1.1.1.2  haad 	return 1;
    995  1.1.1.2  haad }
    996  1.1.1.2  haad #endif	/* UDEV_SYNC_SUPPORT */
    997  1.1.1.2  haad 
    998      1.1  haad static int _version(int argc __attribute((unused)), char **argv __attribute((unused)), void *data __attribute((unused)))
    999      1.1  haad {
   1000      1.1  haad 	char version[80];
   1001      1.1  haad 
   1002      1.1  haad 	if (dm_get_library_version(version, sizeof(version)))
   1003      1.1  haad 		printf("Library version:   %s\n", version);
   1004      1.1  haad 
   1005      1.1  haad 	if (!dm_driver_version(version, sizeof(version)))
   1006      1.1  haad 		return 0;
   1007      1.1  haad 
   1008      1.1  haad 	printf("Driver version:    %s\n", version);
   1009      1.1  haad 
   1010      1.1  haad 	return 1;
   1011      1.1  haad }
   1012      1.1  haad 
   1013      1.1  haad static int _simple(int task, const char *name, uint32_t event_nr, int display)
   1014      1.1  haad {
   1015  1.1.1.2  haad 	uint32_t cookie = 0;
   1016  1.1.1.2  haad 	int udev_wait_flag = task == DM_DEVICE_RESUME ||
   1017  1.1.1.2  haad 			     task == DM_DEVICE_REMOVE;
   1018      1.1  haad 	int r = 0;
   1019      1.1  haad 
   1020      1.1  haad 	struct dm_task *dmt;
   1021      1.1  haad 
   1022      1.1  haad 	if (!(dmt = dm_task_create(task)))
   1023      1.1  haad 		return 0;
   1024      1.1  haad 
   1025      1.1  haad 	if (!_set_task_device(dmt, name, 0))
   1026      1.1  haad 		goto out;
   1027      1.1  haad 
   1028      1.1  haad 	if (event_nr && !dm_task_set_event_nr(dmt, event_nr))
   1029      1.1  haad 		goto out;
   1030      1.1  haad 
   1031      1.1  haad 	if (_switches[NOFLUSH_ARG] && !dm_task_no_flush(dmt))
   1032      1.1  haad 		goto out;
   1033      1.1  haad 
   1034      1.1  haad 	if (_switches[NOOPENCOUNT_ARG] && !dm_task_no_open_count(dmt))
   1035      1.1  haad 		goto out;
   1036      1.1  haad 
   1037  1.1.1.2  haad 	if (_switches[INACTIVE_ARG] && !dm_task_query_inactive_table(dmt))
   1038  1.1.1.2  haad 		goto out;
   1039  1.1.1.2  haad 
   1040      1.1  haad 	if (_switches[NOLOCKFS_ARG] && !dm_task_skip_lockfs(dmt))
   1041      1.1  haad 		goto out;
   1042      1.1  haad 
   1043      1.1  haad 	if (_switches[READAHEAD_ARG] &&
   1044      1.1  haad 	    !dm_task_set_read_ahead(dmt, _int_args[READAHEAD_ARG],
   1045      1.1  haad 				    _read_ahead_flags))
   1046      1.1  haad 		goto out;
   1047      1.1  haad 
   1048  1.1.1.2  haad 	if (udev_wait_flag && !dm_task_set_cookie(dmt, &cookie, 0))
   1049  1.1.1.2  haad 		goto out;
   1050  1.1.1.2  haad 
   1051      1.1  haad 	r = dm_task_run(dmt);
   1052      1.1  haad 
   1053      1.1  haad 	if (r && display && _switches[VERBOSE_ARG])
   1054      1.1  haad 		r = _display_info(dmt);
   1055      1.1  haad 
   1056      1.1  haad       out:
   1057  1.1.1.2  haad 	if (udev_wait_flag)
   1058  1.1.1.2  haad 		(void) dm_udev_wait(cookie);
   1059  1.1.1.2  haad 
   1060      1.1  haad 	dm_task_destroy(dmt);
   1061      1.1  haad 	return r;
   1062      1.1  haad }
   1063      1.1  haad 
   1064      1.1  haad static int _suspend(int argc, char **argv, void *data __attribute((unused)))
   1065      1.1  haad {
   1066      1.1  haad 	return _simple(DM_DEVICE_SUSPEND, argc > 1 ? argv[1] : NULL, 0, 1);
   1067      1.1  haad }
   1068      1.1  haad 
   1069      1.1  haad static int _resume(int argc, char **argv, void *data __attribute((unused)))
   1070      1.1  haad {
   1071      1.1  haad 	return _simple(DM_DEVICE_RESUME, argc > 1 ? argv[1] : NULL, 0, 1);
   1072      1.1  haad }
   1073      1.1  haad 
   1074      1.1  haad static int _clear(int argc, char **argv, void *data __attribute((unused)))
   1075      1.1  haad {
   1076      1.1  haad 	return _simple(DM_DEVICE_CLEAR, argc > 1 ? argv[1] : NULL, 0, 1);
   1077      1.1  haad }
   1078      1.1  haad 
   1079      1.1  haad static int _wait(int argc, char **argv, void *data __attribute((unused)))
   1080      1.1  haad {
   1081      1.1  haad 	const char *name = NULL;
   1082      1.1  haad 
   1083      1.1  haad 	if (!_switches[UUID_ARG] && !_switches[MAJOR_ARG]) {
   1084      1.1  haad 		if (argc == 1) {
   1085      1.1  haad 			err("No device specified.");
   1086      1.1  haad 			return 0;
   1087      1.1  haad 		}
   1088      1.1  haad 		name = argv[1];
   1089      1.1  haad 		argc--, argv++;
   1090      1.1  haad 	}
   1091      1.1  haad 
   1092      1.1  haad 	return _simple(DM_DEVICE_WAITEVENT, name,
   1093      1.1  haad 		       (argc > 1) ? (uint32_t) atoi(argv[argc - 1]) : 0, 1);
   1094      1.1  haad }
   1095      1.1  haad 
   1096      1.1  haad static int _process_all(int argc, char **argv, int silent,
   1097      1.1  haad 			int (*fn) (int argc, char **argv, void *data))
   1098      1.1  haad {
   1099      1.1  haad 	int r = 1;
   1100      1.1  haad 	struct dm_names *names;
   1101      1.1  haad 	unsigned next = 0;
   1102      1.1  haad 
   1103      1.1  haad 	struct dm_task *dmt;
   1104      1.1  haad 
   1105      1.1  haad 	if (!(dmt = dm_task_create(DM_DEVICE_LIST)))
   1106      1.1  haad 		return 0;
   1107      1.1  haad 
   1108      1.1  haad 	if (!dm_task_run(dmt)) {
   1109      1.1  haad 		r = 0;
   1110      1.1  haad 		goto out;
   1111      1.1  haad 	}
   1112      1.1  haad 
   1113      1.1  haad 	if (!(names = dm_task_get_names(dmt))) {
   1114      1.1  haad 		r = 0;
   1115      1.1  haad 		goto out;
   1116      1.1  haad 	}
   1117      1.1  haad 
   1118      1.1  haad 	if (!names->dev) {
   1119      1.1  haad 		if (!silent)
   1120      1.1  haad 			printf("No devices found\n");
   1121      1.1  haad 		goto out;
   1122      1.1  haad 	}
   1123      1.1  haad 
   1124      1.1  haad 	do {
   1125      1.1  haad 		names = (void *) names + next;
   1126      1.1  haad 		if (!fn(argc, argv, (void *) names))
   1127      1.1  haad 			r = 0;
   1128      1.1  haad 		next = names->next;
   1129      1.1  haad 	} while (next);
   1130      1.1  haad 
   1131      1.1  haad       out:
   1132      1.1  haad 	dm_task_destroy(dmt);
   1133      1.1  haad 	return r;
   1134      1.1  haad }
   1135      1.1  haad 
   1136      1.1  haad static uint64_t _get_device_size(const char *name)
   1137      1.1  haad {
   1138      1.1  haad 	uint64_t start, length, size = UINT64_C(0);
   1139      1.1  haad 	struct dm_info info;
   1140      1.1  haad 	char *target_type, *params;
   1141      1.1  haad 	struct dm_task *dmt;
   1142      1.1  haad 	void *next = NULL;
   1143      1.1  haad 
   1144      1.1  haad 	if (!(dmt = dm_task_create(DM_DEVICE_TABLE)))
   1145      1.1  haad 		return 0;
   1146      1.1  haad 
   1147      1.1  haad 	if (!_set_task_device(dmt, name, 0))
   1148      1.1  haad 		goto out;
   1149      1.1  haad 
   1150      1.1  haad 	if (_switches[NOOPENCOUNT_ARG] && !dm_task_no_open_count(dmt))
   1151      1.1  haad 		goto out;
   1152      1.1  haad 
   1153  1.1.1.2  haad 	if (_switches[INACTIVE_ARG] && !dm_task_query_inactive_table(dmt))
   1154  1.1.1.2  haad 		goto out;
   1155  1.1.1.2  haad 
   1156      1.1  haad 	if (!dm_task_run(dmt))
   1157      1.1  haad 		goto out;
   1158      1.1  haad 
   1159      1.1  haad 	if (!dm_task_get_info(dmt, &info) || !info.exists)
   1160      1.1  haad 		goto out;
   1161      1.1  haad 
   1162      1.1  haad 	do {
   1163      1.1  haad 		next = dm_get_next_target(dmt, next, &start, &length,
   1164      1.1  haad 					  &target_type, &params);
   1165      1.1  haad 		size += length;
   1166      1.1  haad 	} while (next);
   1167      1.1  haad 
   1168      1.1  haad       out:
   1169      1.1  haad 	dm_task_destroy(dmt);
   1170      1.1  haad 	return size;
   1171      1.1  haad }
   1172      1.1  haad 
   1173      1.1  haad static int _error_device(int argc __attribute((unused)), char **argv __attribute((unused)), void *data)
   1174      1.1  haad {
   1175      1.1  haad 	struct dm_names *names = (struct dm_names *) data;
   1176      1.1  haad 	struct dm_task *dmt;
   1177      1.1  haad 	const char *name;
   1178      1.1  haad 	uint64_t size;
   1179      1.1  haad 	int r = 0;
   1180      1.1  haad 
   1181      1.1  haad 	if (data)
   1182      1.1  haad 		name = names->name;
   1183      1.1  haad 	else
   1184      1.1  haad 		name = argv[1];
   1185      1.1  haad 
   1186      1.1  haad 	size = _get_device_size(name);
   1187      1.1  haad 
   1188      1.1  haad 	if (!(dmt = dm_task_create(DM_DEVICE_RELOAD)))
   1189      1.1  haad 		return 0;
   1190      1.1  haad 
   1191      1.1  haad 	if (!_set_task_device(dmt, name, 0))
   1192      1.1  haad 		goto error;
   1193      1.1  haad 
   1194      1.1  haad 	if (!dm_task_add_target(dmt, UINT64_C(0), size, "error", ""))
   1195      1.1  haad 		goto error;
   1196      1.1  haad 
   1197      1.1  haad 	if (_switches[READ_ONLY] && !dm_task_set_ro(dmt))
   1198      1.1  haad 		goto error;
   1199      1.1  haad 
   1200      1.1  haad 	if (_switches[NOOPENCOUNT_ARG] && !dm_task_no_open_count(dmt))
   1201      1.1  haad 		goto error;
   1202      1.1  haad 
   1203  1.1.1.2  haad 	if (_switches[INACTIVE_ARG] && !dm_task_query_inactive_table(dmt))
   1204  1.1.1.2  haad 		goto error;
   1205  1.1.1.2  haad 
   1206      1.1  haad 	if (!dm_task_run(dmt))
   1207      1.1  haad 		goto error;
   1208      1.1  haad 
   1209      1.1  haad 	if (!_simple(DM_DEVICE_RESUME, name, 0, 0)) {
   1210      1.1  haad 		_simple(DM_DEVICE_CLEAR, name, 0, 0);
   1211      1.1  haad 		goto error;
   1212      1.1  haad 	}
   1213      1.1  haad 
   1214      1.1  haad 	r = 1;
   1215      1.1  haad 
   1216      1.1  haad error:
   1217      1.1  haad 	dm_task_destroy(dmt);
   1218      1.1  haad 	return r;
   1219      1.1  haad }
   1220      1.1  haad 
   1221      1.1  haad static int _remove(int argc, char **argv, void *data __attribute((unused)))
   1222      1.1  haad {
   1223      1.1  haad 	int r;
   1224      1.1  haad 
   1225      1.1  haad 	if (_switches[FORCE_ARG] && argc > 1)
   1226      1.1  haad 		r = _error_device(argc, argv, NULL);
   1227      1.1  haad 
   1228      1.1  haad 	return _simple(DM_DEVICE_REMOVE, argc > 1 ? argv[1] : NULL, 0, 0);
   1229      1.1  haad }
   1230      1.1  haad 
   1231      1.1  haad static int _count_devices(int argc __attribute((unused)), char **argv __attribute((unused)), void *data __attribute((unused)))
   1232      1.1  haad {
   1233      1.1  haad 	_num_devices++;
   1234      1.1  haad 
   1235      1.1  haad 	return 1;
   1236      1.1  haad }
   1237      1.1  haad 
   1238      1.1  haad static int _remove_all(int argc __attribute((unused)), char **argv __attribute((unused)), void *data __attribute((unused)))
   1239      1.1  haad {
   1240      1.1  haad 	int r;
   1241      1.1  haad 
   1242      1.1  haad 	/* Remove all closed devices */
   1243      1.1  haad 	r =  _simple(DM_DEVICE_REMOVE_ALL, "", 0, 0) | dm_mknodes(NULL);
   1244      1.1  haad 
   1245      1.1  haad 	if (!_switches[FORCE_ARG])
   1246      1.1  haad 		return r;
   1247      1.1  haad 
   1248      1.1  haad 	_num_devices = 0;
   1249      1.1  haad 	r |= _process_all(argc, argv, 1, _count_devices);
   1250      1.1  haad 
   1251      1.1  haad 	/* No devices left? */
   1252      1.1  haad 	if (!_num_devices)
   1253      1.1  haad 		return r;
   1254      1.1  haad 
   1255      1.1  haad 	r |= _process_all(argc, argv, 1, _error_device);
   1256      1.1  haad 	r |= _simple(DM_DEVICE_REMOVE_ALL, "", 0, 0) | dm_mknodes(NULL);
   1257      1.1  haad 
   1258      1.1  haad 	_num_devices = 0;
   1259      1.1  haad 	r |= _process_all(argc, argv, 1, _count_devices);
   1260      1.1  haad 	if (!_num_devices)
   1261      1.1  haad 		return r;
   1262      1.1  haad 
   1263      1.1  haad 	fprintf(stderr, "Unable to remove %d device(s).\n", _num_devices);
   1264      1.1  haad 
   1265      1.1  haad 	return r;
   1266      1.1  haad }
   1267      1.1  haad 
   1268      1.1  haad static void _display_dev(struct dm_task *dmt, const char *name)
   1269      1.1  haad {
   1270      1.1  haad 	struct dm_info info;
   1271      1.1  haad 
   1272      1.1  haad 	if (dm_task_get_info(dmt, &info))
   1273      1.1  haad 		printf("%s\t(%u, %u)\n", name, info.major, info.minor);
   1274      1.1  haad }
   1275      1.1  haad 
   1276      1.1  haad static int _mknodes(int argc, char **argv, void *data __attribute((unused)))
   1277      1.1  haad {
   1278      1.1  haad 	return dm_mknodes(argc > 1 ? argv[1] : NULL);
   1279      1.1  haad }
   1280      1.1  haad 
   1281      1.1  haad static int _exec_command(const char *name)
   1282      1.1  haad {
   1283      1.1  haad 	int n;
   1284      1.1  haad 	static char path[PATH_MAX];
   1285      1.1  haad 	static char *args[ARGS_MAX + 1];
   1286      1.1  haad 	static int argc = 0;
   1287      1.1  haad 	char *c;
   1288      1.1  haad 	pid_t pid;
   1289      1.1  haad 
   1290      1.1  haad 	if (argc < 0)
   1291      1.1  haad 		return 0;
   1292      1.1  haad 
   1293      1.1  haad 	if (!dm_mknodes(name))
   1294      1.1  haad 		return 0;
   1295      1.1  haad 
   1296      1.1  haad 	n = snprintf(path, sizeof(path), "%s/%s", dm_dir(), name);
   1297      1.1  haad 	if (n < 0 || n > (int) sizeof(path) - 1)
   1298      1.1  haad 		return 0;
   1299      1.1  haad 
   1300      1.1  haad 	if (!argc) {
   1301      1.1  haad 		c = _command;
   1302      1.1  haad 		while (argc < ARGS_MAX) {
   1303      1.1  haad 			while (*c && isspace(*c))
   1304      1.1  haad 				c++;
   1305      1.1  haad 			if (!*c)
   1306      1.1  haad 				break;
   1307      1.1  haad 			args[argc++] = c;
   1308      1.1  haad 			while (*c && !isspace(*c))
   1309      1.1  haad 				c++;
   1310      1.1  haad 			if (*c)
   1311      1.1  haad 				*c++ = '\0';
   1312      1.1  haad 		}
   1313      1.1  haad 
   1314      1.1  haad 		if (!argc) {
   1315      1.1  haad 			argc = -1;
   1316      1.1  haad 			return 0;
   1317      1.1  haad 		}
   1318      1.1  haad 
   1319      1.1  haad 		if (argc == ARGS_MAX) {
   1320      1.1  haad 			err("Too many args to --exec\n");
   1321      1.1  haad 			argc = -1;
   1322      1.1  haad 			return 0;
   1323      1.1  haad 		}
   1324      1.1  haad 
   1325      1.1  haad 		args[argc++] = path;
   1326      1.1  haad 		args[argc] = NULL;
   1327      1.1  haad 	}
   1328      1.1  haad 
   1329      1.1  haad 	if (!(pid = fork())) {
   1330      1.1  haad 		execvp(args[0], args);
   1331  1.1.1.2  haad 		_exit(127);
   1332      1.1  haad 	} else if (pid < (pid_t) 0)
   1333      1.1  haad 		return 0;
   1334      1.1  haad 
   1335      1.1  haad 	TEMP_FAILURE_RETRY(waitpid(pid, NULL, 0));
   1336      1.1  haad 
   1337      1.1  haad 	return 1;
   1338      1.1  haad }
   1339      1.1  haad 
   1340      1.1  haad static int _status(int argc, char **argv, void *data)
   1341      1.1  haad {
   1342      1.1  haad 	int r = 0;
   1343      1.1  haad 	struct dm_task *dmt;
   1344      1.1  haad 	void *next = NULL;
   1345      1.1  haad 	uint64_t start, length;
   1346      1.1  haad 	char *target_type = NULL;
   1347      1.1  haad 	char *params, *c;
   1348      1.1  haad 	int cmd;
   1349      1.1  haad 	struct dm_names *names = (struct dm_names *) data;
   1350      1.1  haad 	const char *name = NULL;
   1351      1.1  haad 	int matched = 0;
   1352      1.1  haad 	int ls_only = 0;
   1353      1.1  haad 	struct dm_info info;
   1354      1.1  haad 
   1355      1.1  haad 	if (data)
   1356      1.1  haad 		name = names->name;
   1357      1.1  haad 	else {
   1358      1.1  haad 		if (argc == 1 && !_switches[UUID_ARG] && !_switches[MAJOR_ARG])
   1359      1.1  haad 			return _process_all(argc, argv, 0, _status);
   1360      1.1  haad 		if (argc == 2)
   1361      1.1  haad 			name = argv[1];
   1362      1.1  haad 	}
   1363      1.1  haad 
   1364      1.1  haad 	if (!strcmp(argv[0], "table"))
   1365      1.1  haad 		cmd = DM_DEVICE_TABLE;
   1366      1.1  haad 	else
   1367      1.1  haad 		cmd = DM_DEVICE_STATUS;
   1368      1.1  haad 
   1369      1.1  haad 	if (!strcmp(argv[0], "ls"))
   1370      1.1  haad 		ls_only = 1;
   1371      1.1  haad 
   1372      1.1  haad 	if (!(dmt = dm_task_create(cmd)))
   1373      1.1  haad 		return 0;
   1374      1.1  haad 
   1375      1.1  haad 	if (!_set_task_device(dmt, name, 0))
   1376      1.1  haad 		goto out;
   1377      1.1  haad 
   1378      1.1  haad 	if (_switches[NOOPENCOUNT_ARG] && !dm_task_no_open_count(dmt))
   1379      1.1  haad 		goto out;
   1380      1.1  haad 
   1381  1.1.1.2  haad 	if (_switches[INACTIVE_ARG] && !dm_task_query_inactive_table(dmt))
   1382  1.1.1.2  haad 		goto out;
   1383  1.1.1.2  haad 
   1384      1.1  haad 	if (!dm_task_run(dmt))
   1385      1.1  haad 		goto out;
   1386      1.1  haad 
   1387      1.1  haad 	if (!dm_task_get_info(dmt, &info) || !info.exists)
   1388      1.1  haad 		goto out;
   1389      1.1  haad 
   1390      1.1  haad 	if (!name)
   1391      1.1  haad 		name = dm_task_get_name(dmt);
   1392      1.1  haad 
   1393      1.1  haad 	/* Fetch targets and print 'em */
   1394      1.1  haad 	do {
   1395      1.1  haad 		next = dm_get_next_target(dmt, next, &start, &length,
   1396      1.1  haad 					  &target_type, &params);
   1397      1.1  haad 		/* Skip if target type doesn't match */
   1398      1.1  haad 		if (_switches[TARGET_ARG] &&
   1399      1.1  haad 		    (!target_type || strcmp(target_type, _target)))
   1400      1.1  haad 			continue;
   1401      1.1  haad 		if (ls_only) {
   1402      1.1  haad 			if (!_switches[EXEC_ARG] || !_command ||
   1403      1.1  haad 			    _switches[VERBOSE_ARG])
   1404      1.1  haad 				_display_dev(dmt, name);
   1405      1.1  haad 			next = NULL;
   1406      1.1  haad 		} else if (!_switches[EXEC_ARG] || !_command ||
   1407      1.1  haad 			   _switches[VERBOSE_ARG]) {
   1408      1.1  haad 			if (!matched && _switches[VERBOSE_ARG])
   1409      1.1  haad 				_display_info(dmt);
   1410      1.1  haad 			if (data && !_switches[VERBOSE_ARG])
   1411      1.1  haad 				printf("%s: ", name);
   1412      1.1  haad 			if (target_type) {
   1413      1.1  haad 				/* Suppress encryption key */
   1414      1.1  haad 				if (!_switches[SHOWKEYS_ARG] &&
   1415      1.1  haad 				    cmd == DM_DEVICE_TABLE &&
   1416      1.1  haad 				    !strcmp(target_type, "crypt")) {
   1417      1.1  haad 					c = params;
   1418      1.1  haad 					while (*c && *c != ' ')
   1419      1.1  haad 						c++;
   1420      1.1  haad 					if (*c)
   1421      1.1  haad 						c++;
   1422      1.1  haad 					while (*c && *c != ' ')
   1423      1.1  haad 						*c++ = '0';
   1424      1.1  haad 				}
   1425      1.1  haad 				printf("%" PRIu64 " %" PRIu64 " %s %s",
   1426      1.1  haad 				       start, length, target_type, params);
   1427      1.1  haad 			}
   1428      1.1  haad 			printf("\n");
   1429      1.1  haad 		}
   1430      1.1  haad 		matched = 1;
   1431      1.1  haad 	} while (next);
   1432      1.1  haad 
   1433      1.1  haad 	if (data && _switches[VERBOSE_ARG] && matched && !ls_only)
   1434      1.1  haad 		printf("\n");
   1435      1.1  haad 
   1436      1.1  haad 	if (matched && _switches[EXEC_ARG] && _command && !_exec_command(name))
   1437      1.1  haad 		goto out;
   1438      1.1  haad 
   1439      1.1  haad 	r = 1;
   1440      1.1  haad 
   1441      1.1  haad       out:
   1442      1.1  haad 	dm_task_destroy(dmt);
   1443      1.1  haad 	return r;
   1444      1.1  haad }
   1445      1.1  haad 
   1446      1.1  haad /* Show target names and their version numbers */
   1447      1.1  haad static int _targets(int argc __attribute((unused)), char **argv __attribute((unused)), void *data __attribute((unused)))
   1448      1.1  haad {
   1449      1.1  haad 	int r = 0;
   1450      1.1  haad 	struct dm_task *dmt;
   1451      1.1  haad 	struct dm_versions *target;
   1452      1.1  haad 	struct dm_versions *last_target;
   1453      1.1  haad 
   1454      1.1  haad 	if (!(dmt = dm_task_create(DM_DEVICE_LIST_VERSIONS)))
   1455      1.1  haad 		return 0;
   1456      1.1  haad 
   1457      1.1  haad 	if (!dm_task_run(dmt))
   1458      1.1  haad 		goto out;
   1459      1.1  haad 
   1460      1.1  haad 	target = dm_task_get_versions(dmt);
   1461      1.1  haad 
   1462      1.1  haad 	/* Fetch targets and print 'em */
   1463      1.1  haad 	do {
   1464      1.1  haad 		last_target = target;
   1465      1.1  haad 
   1466      1.1  haad 		printf("%-16s v%d.%d.%d\n", target->name, target->version[0],
   1467      1.1  haad 		       target->version[1], target->version[2]);
   1468      1.1  haad 
   1469      1.1  haad 		target = (void *) target + target->next;
   1470      1.1  haad 	} while (last_target != target);
   1471      1.1  haad 
   1472      1.1  haad 	r = 1;
   1473      1.1  haad 
   1474      1.1  haad       out:
   1475      1.1  haad 	dm_task_destroy(dmt);
   1476      1.1  haad 	return r;
   1477      1.1  haad }
   1478      1.1  haad 
   1479      1.1  haad static int _info(int argc, char **argv, void *data)
   1480      1.1  haad {
   1481      1.1  haad 	int r = 0;
   1482      1.1  haad 
   1483      1.1  haad 	struct dm_task *dmt;
   1484      1.1  haad 	struct dm_names *names = (struct dm_names *) data;
   1485      1.1  haad 	char *name = NULL;
   1486      1.1  haad 
   1487      1.1  haad 	if (data)
   1488      1.1  haad 		name = names->name;
   1489      1.1  haad 	else {
   1490      1.1  haad 		if (argc == 1 && !_switches[UUID_ARG] && !_switches[MAJOR_ARG])
   1491      1.1  haad 			return _process_all(argc, argv, 0, _info);
   1492      1.1  haad 		if (argc == 2)
   1493      1.1  haad 			name = argv[1];
   1494      1.1  haad 	}
   1495      1.1  haad 
   1496      1.1  haad 	if (!(dmt = dm_task_create(DM_DEVICE_INFO)))
   1497      1.1  haad 		return 0;
   1498      1.1  haad 
   1499      1.1  haad 	if (!_set_task_device(dmt, name, 0))
   1500      1.1  haad 		goto out;
   1501      1.1  haad 
   1502      1.1  haad 	if (_switches[NOOPENCOUNT_ARG] && !dm_task_no_open_count(dmt))
   1503      1.1  haad 		goto out;
   1504      1.1  haad 
   1505  1.1.1.2  haad 	if (_switches[INACTIVE_ARG] && !dm_task_query_inactive_table(dmt))
   1506  1.1.1.2  haad 		goto out;
   1507  1.1.1.2  haad 
   1508      1.1  haad 	if (!dm_task_run(dmt))
   1509      1.1  haad 		goto out;
   1510      1.1  haad 
   1511      1.1  haad 	r = _display_info(dmt);
   1512      1.1  haad 
   1513      1.1  haad       out:
   1514      1.1  haad 	dm_task_destroy(dmt);
   1515      1.1  haad 	return r;
   1516      1.1  haad }
   1517      1.1  haad 
   1518      1.1  haad static int _deps(int argc, char **argv, void *data)
   1519      1.1  haad {
   1520      1.1  haad 	int r = 0;
   1521      1.1  haad 	uint32_t i;
   1522      1.1  haad 	struct dm_deps *deps;
   1523      1.1  haad 	struct dm_task *dmt;
   1524      1.1  haad 	struct dm_info info;
   1525      1.1  haad 	struct dm_names *names = (struct dm_names *) data;
   1526      1.1  haad 	char *name = NULL;
   1527      1.1  haad 
   1528      1.1  haad 	if (data)
   1529      1.1  haad 		name = names->name;
   1530      1.1  haad 	else {
   1531      1.1  haad 		if (argc == 1 && !_switches[UUID_ARG] && !_switches[MAJOR_ARG])
   1532      1.1  haad 			return _process_all(argc, argv, 0, _deps);
   1533      1.1  haad 		if (argc == 2)
   1534      1.1  haad 			name = argv[1];
   1535      1.1  haad 	}
   1536      1.1  haad 
   1537      1.1  haad 	if (!(dmt = dm_task_create(DM_DEVICE_DEPS)))
   1538      1.1  haad 		return 0;
   1539      1.1  haad 
   1540      1.1  haad 	if (!_set_task_device(dmt, name, 0))
   1541      1.1  haad 		goto out;
   1542      1.1  haad 
   1543      1.1  haad 	if (_switches[NOOPENCOUNT_ARG] && !dm_task_no_open_count(dmt))
   1544      1.1  haad 		goto out;
   1545      1.1  haad 
   1546  1.1.1.2  haad 	if (_switches[INACTIVE_ARG] && !dm_task_query_inactive_table(dmt))
   1547  1.1.1.2  haad 		goto out;
   1548  1.1.1.2  haad 
   1549      1.1  haad 	if (!dm_task_run(dmt))
   1550      1.1  haad 		goto out;
   1551      1.1  haad 
   1552      1.1  haad 	if (!dm_task_get_info(dmt, &info))
   1553      1.1  haad 		goto out;
   1554      1.1  haad 
   1555      1.1  haad 	if (!(deps = dm_task_get_deps(dmt)))
   1556      1.1  haad 		goto out;
   1557      1.1  haad 
   1558      1.1  haad 	if (!info.exists) {
   1559      1.1  haad 		printf("Device does not exist.\n");
   1560      1.1  haad 		r = 1;
   1561      1.1  haad 		goto out;
   1562      1.1  haad 	}
   1563      1.1  haad 
   1564      1.1  haad 	if (_switches[VERBOSE_ARG])
   1565      1.1  haad 		_display_info(dmt);
   1566      1.1  haad 
   1567      1.1  haad 	if (data && !_switches[VERBOSE_ARG])
   1568      1.1  haad 		printf("%s: ", name);
   1569      1.1  haad 	printf("%d dependencies\t:", deps->count);
   1570      1.1  haad 
   1571      1.1  haad 	for (i = 0; i < deps->count; i++)
   1572      1.1  haad 		printf(" (%d, %d)",
   1573      1.1  haad 		       (int) MAJOR(deps->device[i]),
   1574      1.1  haad 		       (int) MINOR(deps->device[i]));
   1575      1.1  haad 	printf("\n");
   1576      1.1  haad 
   1577      1.1  haad 	if (data && _switches[VERBOSE_ARG])
   1578      1.1  haad 		printf("\n");
   1579      1.1  haad 
   1580      1.1  haad 	r = 1;
   1581      1.1  haad 
   1582      1.1  haad       out:
   1583      1.1  haad 	dm_task_destroy(dmt);
   1584      1.1  haad 	return r;
   1585      1.1  haad }
   1586      1.1  haad 
   1587      1.1  haad static int _display_name(int argc __attribute((unused)), char **argv __attribute((unused)), void *data)
   1588      1.1  haad {
   1589      1.1  haad 	struct dm_names *names = (struct dm_names *) data;
   1590      1.1  haad 
   1591      1.1  haad 	printf("%s\t(%d, %d)\n", names->name,
   1592      1.1  haad 	       (int) MAJOR(names->dev), (int) MINOR(names->dev));
   1593      1.1  haad 
   1594      1.1  haad 	return 1;
   1595      1.1  haad }
   1596      1.1  haad 
   1597      1.1  haad /*
   1598      1.1  haad  * Tree drawing code
   1599      1.1  haad  */
   1600      1.1  haad 
   1601      1.1  haad enum {
   1602      1.1  haad 	TR_DEVICE=0,	/* display device major:minor number */
   1603      1.1  haad 	TR_TABLE,
   1604      1.1  haad 	TR_STATUS,
   1605      1.1  haad 	TR_ACTIVE,
   1606      1.1  haad 	TR_RW,
   1607      1.1  haad 	TR_OPENCOUNT,
   1608      1.1  haad 	TR_UUID,
   1609      1.1  haad 	TR_COMPACT,
   1610      1.1  haad 	TR_TRUNCATE,
   1611      1.1  haad 	TR_BOTTOMUP,
   1612      1.1  haad 	NUM_TREEMODE,
   1613      1.1  haad };
   1614      1.1  haad 
   1615      1.1  haad static int _tree_switches[NUM_TREEMODE];
   1616      1.1  haad 
   1617      1.1  haad #define TR_PRINT_ATTRIBUTE ( _tree_switches[TR_ACTIVE] || \
   1618      1.1  haad 			     _tree_switches[TR_RW] || \
   1619      1.1  haad 			     _tree_switches[TR_OPENCOUNT] || \
   1620      1.1  haad 			     _tree_switches[TR_UUID] )
   1621      1.1  haad 
   1622      1.1  haad #define TR_PRINT_TARGETS ( _tree_switches[TR_TABLE] || \
   1623      1.1  haad 			   _tree_switches[TR_STATUS] )
   1624      1.1  haad 
   1625      1.1  haad /* Compact - fewer newlines */
   1626      1.1  haad #define TR_PRINT_COMPACT (_tree_switches[TR_COMPACT] && \
   1627      1.1  haad 			  !TR_PRINT_ATTRIBUTE && \
   1628      1.1  haad 			  !TR_PRINT_TARGETS)
   1629      1.1  haad 
   1630      1.1  haad /* FIXME Get rid of this */
   1631      1.1  haad #define MAX_DEPTH 100
   1632      1.1  haad 
   1633      1.1  haad /* Drawing character definition from pstree */
   1634      1.1  haad /* [pstree comment] UTF-8 defines by Johan Myreen, updated by Ben Winslow */
   1635      1.1  haad #define UTF_V	"\342\224\202"	/* U+2502, Vertical line drawing char */
   1636      1.1  haad #define UTF_VR	"\342\224\234"	/* U+251C, Vertical and right */
   1637      1.1  haad #define UTF_H	"\342\224\200"	/* U+2500, Horizontal */
   1638      1.1  haad #define UTF_UR	"\342\224\224"	/* U+2514, Up and right */
   1639      1.1  haad #define UTF_HD	"\342\224\254"	/* U+252C, Horizontal and down */
   1640      1.1  haad 
   1641      1.1  haad #define VT_BEG	"\033(0\017"	/* use graphic chars */
   1642      1.1  haad #define VT_END	"\033(B"	/* back to normal char set */
   1643      1.1  haad #define VT_V	"x"		/* see UTF definitions above */
   1644      1.1  haad #define VT_VR	"t"
   1645      1.1  haad #define VT_H	"q"
   1646      1.1  haad #define VT_UR	"m"
   1647      1.1  haad #define VT_HD	"w"
   1648      1.1  haad 
   1649      1.1  haad static struct {
   1650      1.1  haad 	const char *empty_2;	/*    */
   1651      1.1  haad 	const char *branch_2;	/* |- */
   1652      1.1  haad 	const char *vert_2;	/* |  */
   1653      1.1  haad 	const char *last_2;	/* `- */
   1654      1.1  haad 	const char *single_3;	/* --- */
   1655      1.1  haad 	const char *first_3;	/* -+- */
   1656      1.1  haad }
   1657      1.1  haad _tsym_ascii = {
   1658      1.1  haad 	"  ",
   1659      1.1  haad 	"|-",
   1660      1.1  haad 	"| ",
   1661      1.1  haad 	"`-",
   1662      1.1  haad 	"---",
   1663      1.1  haad 	"-+-"
   1664      1.1  haad },
   1665      1.1  haad _tsym_utf = {
   1666      1.1  haad 	"  ",
   1667      1.1  haad 	UTF_VR UTF_H,
   1668      1.1  haad 	UTF_V " ",
   1669      1.1  haad 	UTF_UR UTF_H,
   1670      1.1  haad 	UTF_H UTF_H UTF_H,
   1671      1.1  haad 	UTF_H UTF_HD UTF_H
   1672      1.1  haad },
   1673      1.1  haad _tsym_vt100 = {
   1674      1.1  haad 	"  ",
   1675      1.1  haad 	VT_BEG VT_VR VT_H VT_END,
   1676      1.1  haad 	VT_BEG VT_V VT_END " ",
   1677      1.1  haad 	VT_BEG VT_UR VT_H VT_END,
   1678      1.1  haad 	VT_BEG VT_H VT_H VT_H VT_END,
   1679      1.1  haad 	VT_BEG VT_H VT_HD VT_H VT_END
   1680      1.1  haad },
   1681      1.1  haad *_tsym = &_tsym_ascii;
   1682      1.1  haad 
   1683      1.1  haad /*
   1684      1.1  haad  * Tree drawing functions.
   1685      1.1  haad  */
   1686      1.1  haad /* FIXME Get rid of these statics - use dynamic struct */
   1687      1.1  haad /* FIXME Explain what these vars are for */
   1688      1.1  haad static int _tree_width[MAX_DEPTH], _tree_more[MAX_DEPTH];
   1689      1.1  haad static int _termwidth = 80;	/* Maximum output width */
   1690      1.1  haad static int _cur_x = 1;		/* Current horizontal output position */
   1691      1.1  haad static char _last_char = 0;
   1692      1.1  haad 
   1693      1.1  haad static void _out_char(const unsigned c)
   1694      1.1  haad {
   1695      1.1  haad 	/* Only first UTF-8 char counts */
   1696      1.1  haad 	_cur_x += ((c & 0xc0) != 0x80);
   1697      1.1  haad 
   1698      1.1  haad 	if (!_tree_switches[TR_TRUNCATE]) {
   1699      1.1  haad 		putchar((int) c);
   1700      1.1  haad 		return;
   1701      1.1  haad 	}
   1702      1.1  haad 
   1703      1.1  haad 	/* Truncation? */
   1704      1.1  haad 	if (_cur_x <= _termwidth)
   1705      1.1  haad 		putchar((int) c);
   1706      1.1  haad 
   1707      1.1  haad 	if (_cur_x == _termwidth + 1 && ((c & 0xc0) != 0x80)) {
   1708      1.1  haad 		if (_last_char || (c & 0x80)) {
   1709      1.1  haad 			putchar('.');
   1710      1.1  haad 			putchar('.');
   1711      1.1  haad 			putchar('.');
   1712      1.1  haad 		} else {
   1713      1.1  haad 			_last_char = c;
   1714      1.1  haad 			_cur_x--;
   1715      1.1  haad 		}
   1716      1.1  haad 	}
   1717      1.1  haad }
   1718      1.1  haad 
   1719      1.1  haad static void _out_string(const char *str)
   1720      1.1  haad {
   1721      1.1  haad 	while (*str)
   1722      1.1  haad 		_out_char((unsigned char) *str++);
   1723      1.1  haad }
   1724      1.1  haad 
   1725      1.1  haad /* non-negative integers only */
   1726      1.1  haad static unsigned _out_int(unsigned num)
   1727      1.1  haad {
   1728      1.1  haad 	unsigned digits = 0;
   1729      1.1  haad 	unsigned divi;
   1730      1.1  haad 
   1731      1.1  haad 	if (!num) {
   1732      1.1  haad 		_out_char('0');
   1733      1.1  haad 		return 1;
   1734      1.1  haad 	}
   1735      1.1  haad 
   1736      1.1  haad 	/* non zero case */
   1737      1.1  haad 	for (divi = 1; num / divi; divi *= 10)
   1738      1.1  haad 		digits++;
   1739      1.1  haad 
   1740      1.1  haad 	for (divi /= 10; divi; divi /= 10)
   1741      1.1  haad 		_out_char('0' + (num / divi) % 10);
   1742      1.1  haad 
   1743      1.1  haad 	return digits;
   1744      1.1  haad }
   1745      1.1  haad 
   1746      1.1  haad static void _out_newline(void)
   1747      1.1  haad {
   1748      1.1  haad 	if (_last_char && _cur_x == _termwidth)
   1749      1.1  haad 		putchar(_last_char);
   1750      1.1  haad 	_last_char = 0;
   1751      1.1  haad 	putchar('\n');
   1752      1.1  haad 	_cur_x = 1;
   1753      1.1  haad }
   1754      1.1  haad 
   1755      1.1  haad static void _out_prefix(unsigned depth)
   1756      1.1  haad {
   1757      1.1  haad 	unsigned x, d;
   1758      1.1  haad 
   1759      1.1  haad 	for (d = 0; d < depth; d++) {
   1760      1.1  haad 		for (x = _tree_width[d] + 1; x > 0; x--)
   1761      1.1  haad 			_out_char(' ');
   1762      1.1  haad 
   1763      1.1  haad 		_out_string(d == depth - 1 ?
   1764      1.1  haad 				!_tree_more[depth] ? _tsym->last_2 : _tsym->branch_2
   1765      1.1  haad 			   : _tree_more[d + 1] ?
   1766      1.1  haad 				_tsym->vert_2 : _tsym->empty_2);
   1767      1.1  haad 	}
   1768      1.1  haad }
   1769      1.1  haad 
   1770      1.1  haad /*
   1771      1.1  haad  * Display tree
   1772      1.1  haad  */
   1773      1.1  haad static void _display_tree_attributes(struct dm_tree_node *node)
   1774      1.1  haad {
   1775      1.1  haad 	int attr = 0;
   1776      1.1  haad 	const char *uuid;
   1777      1.1  haad 	const struct dm_info *info;
   1778      1.1  haad 
   1779      1.1  haad 	uuid = dm_tree_node_get_uuid(node);
   1780      1.1  haad 	info = dm_tree_node_get_info(node);
   1781      1.1  haad 
   1782      1.1  haad 	if (!info->exists)
   1783      1.1  haad 		return;
   1784      1.1  haad 
   1785      1.1  haad 	if (_tree_switches[TR_ACTIVE]) {
   1786      1.1  haad 		_out_string(attr++ ? ", " : " [");
   1787      1.1  haad 		_out_string(info->suspended ? "SUSPENDED" : "ACTIVE");
   1788      1.1  haad 	}
   1789      1.1  haad 
   1790      1.1  haad 	if (_tree_switches[TR_RW]) {
   1791      1.1  haad 		_out_string(attr++ ? ", " : " [");
   1792      1.1  haad 		_out_string(info->read_only ? "RO" : "RW");
   1793      1.1  haad 	}
   1794      1.1  haad 
   1795      1.1  haad 	if (_tree_switches[TR_OPENCOUNT]) {
   1796      1.1  haad 		_out_string(attr++ ? ", " : " [");
   1797      1.1  haad 		(void) _out_int((unsigned) info->open_count);
   1798      1.1  haad 	}
   1799      1.1  haad 
   1800      1.1  haad 	if (_tree_switches[TR_UUID]) {
   1801      1.1  haad 		_out_string(attr++ ? ", " : " [");
   1802      1.1  haad 		_out_string(uuid && *uuid ? uuid : "");
   1803      1.1  haad 	}
   1804      1.1  haad 
   1805      1.1  haad 	if (attr)
   1806      1.1  haad 		_out_char(']');
   1807      1.1  haad }
   1808      1.1  haad 
   1809      1.1  haad static void _display_tree_node(struct dm_tree_node *node, unsigned depth,
   1810      1.1  haad 			       unsigned first_child __attribute((unused)),
   1811      1.1  haad 			       unsigned last_child, unsigned has_children)
   1812      1.1  haad {
   1813      1.1  haad 	int offset;
   1814      1.1  haad 	const char *name;
   1815      1.1  haad 	const struct dm_info *info;
   1816      1.1  haad 	int first_on_line = 0;
   1817      1.1  haad 
   1818      1.1  haad 	/* Sub-tree for targets has 2 more depth */
   1819      1.1  haad 	if (depth + 2 > MAX_DEPTH)
   1820      1.1  haad 		return;
   1821      1.1  haad 
   1822      1.1  haad 	name = dm_tree_node_get_name(node);
   1823      1.1  haad 
   1824      1.1  haad 	if ((!name || !*name) && !_tree_switches[TR_DEVICE])
   1825      1.1  haad 		return;
   1826      1.1  haad 
   1827      1.1  haad 	/* Indicate whether there are more nodes at this depth */
   1828      1.1  haad 	_tree_more[depth] = !last_child;
   1829      1.1  haad 	_tree_width[depth] = 0;
   1830      1.1  haad 
   1831      1.1  haad 	if (_cur_x == 1)
   1832      1.1  haad 		first_on_line = 1;
   1833      1.1  haad 
   1834      1.1  haad 	if (!TR_PRINT_COMPACT || first_on_line)
   1835      1.1  haad 		_out_prefix(depth);
   1836      1.1  haad 
   1837      1.1  haad 	/* Remember the starting point for compact */
   1838      1.1  haad 	offset = _cur_x;
   1839      1.1  haad 
   1840      1.1  haad 	if (TR_PRINT_COMPACT && !first_on_line)
   1841      1.1  haad 		_out_string(_tree_more[depth] ? _tsym->first_3 : _tsym->single_3);
   1842      1.1  haad 
   1843      1.1  haad 	/* display node */
   1844      1.1  haad 	if (name)
   1845      1.1  haad 		_out_string(name);
   1846      1.1  haad 
   1847      1.1  haad 	info = dm_tree_node_get_info(node);
   1848      1.1  haad 
   1849      1.1  haad 	if (_tree_switches[TR_DEVICE]) {
   1850      1.1  haad 		_out_string(name ? " (" : "(");
   1851      1.1  haad 		(void) _out_int(info->major);
   1852      1.1  haad 		_out_char(':');
   1853      1.1  haad 		(void) _out_int(info->minor);
   1854      1.1  haad 		_out_char(')');
   1855      1.1  haad 	}
   1856      1.1  haad 
   1857      1.1  haad 	/* display additional info */
   1858      1.1  haad 	if (TR_PRINT_ATTRIBUTE)
   1859      1.1  haad 		_display_tree_attributes(node);
   1860      1.1  haad 
   1861      1.1  haad 	if (TR_PRINT_COMPACT)
   1862      1.1  haad 		_tree_width[depth] = _cur_x - offset;
   1863      1.1  haad 
   1864      1.1  haad 	if (!TR_PRINT_COMPACT || !has_children)
   1865      1.1  haad 		_out_newline();
   1866      1.1  haad 
   1867      1.1  haad 	if (TR_PRINT_TARGETS) {
   1868      1.1  haad 		_tree_more[depth + 1] = has_children;
   1869      1.1  haad 		// FIXME _display_tree_targets(name, depth + 2);
   1870      1.1  haad 	}
   1871      1.1  haad }
   1872      1.1  haad 
   1873      1.1  haad /*
   1874      1.1  haad  * Walk the dependency tree
   1875      1.1  haad  */
   1876      1.1  haad static void _display_tree_walk_children(struct dm_tree_node *node,
   1877      1.1  haad 					unsigned depth)
   1878      1.1  haad {
   1879      1.1  haad 	struct dm_tree_node *child, *next_child;
   1880      1.1  haad 	void *handle = NULL;
   1881      1.1  haad 	uint32_t inverted = _tree_switches[TR_BOTTOMUP];
   1882      1.1  haad 	unsigned first_child = 1;
   1883      1.1  haad 	unsigned has_children;
   1884      1.1  haad 
   1885      1.1  haad 	next_child = dm_tree_next_child(&handle, node, inverted);
   1886      1.1  haad 
   1887      1.1  haad 	while ((child = next_child)) {
   1888      1.1  haad 		next_child = dm_tree_next_child(&handle, node, inverted);
   1889      1.1  haad 		has_children =
   1890      1.1  haad 		    dm_tree_node_num_children(child, inverted) ? 1 : 0;
   1891      1.1  haad 
   1892      1.1  haad 		_display_tree_node(child, depth, first_child,
   1893      1.1  haad 				   next_child ? 0U : 1U, has_children);
   1894      1.1  haad 
   1895      1.1  haad 		if (has_children)
   1896      1.1  haad 			_display_tree_walk_children(child, depth + 1);
   1897      1.1  haad 
   1898      1.1  haad 		first_child = 0;
   1899      1.1  haad 	}
   1900      1.1  haad }
   1901      1.1  haad 
   1902      1.1  haad static int _add_dep(int argc __attribute((unused)), char **argv __attribute((unused)), void *data)
   1903      1.1  haad {
   1904      1.1  haad 	struct dm_names *names = (struct dm_names *) data;
   1905      1.1  haad 
   1906      1.1  haad 	if (!dm_tree_add_dev(_dtree, (unsigned) MAJOR(names->dev), (unsigned) MINOR(names->dev)))
   1907      1.1  haad 		return 0;
   1908      1.1  haad 
   1909      1.1  haad 	return 1;
   1910      1.1  haad }
   1911      1.1  haad 
   1912      1.1  haad /*
   1913      1.1  haad  * Create and walk dependency tree
   1914      1.1  haad  */
   1915      1.1  haad static int _build_whole_deptree(void)
   1916      1.1  haad {
   1917      1.1  haad 	if (_dtree)
   1918      1.1  haad 		return 1;
   1919      1.1  haad 
   1920      1.1  haad 	if (!(_dtree = dm_tree_create()))
   1921      1.1  haad 		return 0;
   1922      1.1  haad 
   1923      1.1  haad 	if (!_process_all(0, NULL, 0, _add_dep))
   1924      1.1  haad 		return 0;
   1925      1.1  haad 
   1926      1.1  haad 	return 1;
   1927      1.1  haad }
   1928      1.1  haad 
   1929      1.1  haad static int _display_tree(int argc __attribute((unused)),
   1930      1.1  haad 			 char **argv __attribute((unused)),
   1931      1.1  haad 			 void *data __attribute((unused)))
   1932      1.1  haad {
   1933      1.1  haad 	if (!_build_whole_deptree())
   1934      1.1  haad 		return 0;
   1935      1.1  haad 
   1936      1.1  haad 	_display_tree_walk_children(dm_tree_find_node(_dtree, 0, 0), 0);
   1937      1.1  haad 
   1938      1.1  haad 	return 1;
   1939      1.1  haad }
   1940      1.1  haad 
   1941      1.1  haad /*
   1942      1.1  haad  * Report device information
   1943      1.1  haad  */
   1944      1.1  haad 
   1945      1.1  haad /* dm specific display functions */
   1946      1.1  haad 
   1947      1.1  haad static int _int32_disp(struct dm_report *rh,
   1948      1.1  haad 		       struct dm_pool *mem __attribute((unused)),
   1949      1.1  haad 		       struct dm_report_field *field, const void *data,
   1950      1.1  haad 		       void *private __attribute((unused)))
   1951      1.1  haad {
   1952      1.1  haad 	const int32_t value = *(const int32_t *)data;
   1953      1.1  haad 
   1954      1.1  haad 	return dm_report_field_int32(rh, field, &value);
   1955      1.1  haad }
   1956      1.1  haad 
   1957      1.1  haad static int _uint32_disp(struct dm_report *rh,
   1958      1.1  haad 			struct dm_pool *mem __attribute((unused)),
   1959      1.1  haad 			struct dm_report_field *field, const void *data,
   1960      1.1  haad 			void *private __attribute((unused)))
   1961      1.1  haad {
   1962      1.1  haad 	const uint32_t value = *(const int32_t *)data;
   1963      1.1  haad 
   1964      1.1  haad 	return dm_report_field_uint32(rh, field, &value);
   1965      1.1  haad }
   1966      1.1  haad 
   1967      1.1  haad static int _dm_name_disp(struct dm_report *rh,
   1968      1.1  haad 			 struct dm_pool *mem __attribute((unused)),
   1969      1.1  haad 			 struct dm_report_field *field, const void *data,
   1970      1.1  haad 			 void *private __attribute((unused)))
   1971      1.1  haad {
   1972      1.1  haad 	const char *name = dm_task_get_name((const struct dm_task *) data);
   1973      1.1  haad 
   1974      1.1  haad 	return dm_report_field_string(rh, field, &name);
   1975      1.1  haad }
   1976      1.1  haad 
   1977      1.1  haad static int _dm_uuid_disp(struct dm_report *rh,
   1978      1.1  haad 			 struct dm_pool *mem __attribute((unused)),
   1979      1.1  haad 			 struct dm_report_field *field,
   1980      1.1  haad 			 const void *data, void *private __attribute((unused)))
   1981      1.1  haad {
   1982      1.1  haad 	const char *uuid = dm_task_get_uuid((const struct dm_task *) data);
   1983      1.1  haad 
   1984      1.1  haad 	if (!uuid || !*uuid)
   1985      1.1  haad 		uuid = "";
   1986      1.1  haad 
   1987      1.1  haad 	return dm_report_field_string(rh, field, &uuid);
   1988      1.1  haad }
   1989      1.1  haad 
   1990      1.1  haad static int _dm_read_ahead_disp(struct dm_report *rh,
   1991      1.1  haad 			       struct dm_pool *mem __attribute((unused)),
   1992      1.1  haad 			       struct dm_report_field *field, const void *data,
   1993      1.1  haad 			       void *private __attribute((unused)))
   1994      1.1  haad {
   1995      1.1  haad 	uint32_t value;
   1996      1.1  haad 
   1997      1.1  haad 	if (!dm_task_get_read_ahead((const struct dm_task *) data, &value))
   1998      1.1  haad 		value = 0;
   1999      1.1  haad 
   2000      1.1  haad 	return dm_report_field_uint32(rh, field, &value);
   2001      1.1  haad }
   2002      1.1  haad 
   2003      1.1  haad static int _dm_info_status_disp(struct dm_report *rh,
   2004      1.1  haad 				struct dm_pool *mem __attribute((unused)),
   2005      1.1  haad 				struct dm_report_field *field, const void *data,
   2006      1.1  haad 				void *private __attribute((unused)))
   2007      1.1  haad {
   2008      1.1  haad 	char buf[5];
   2009      1.1  haad 	const char *s = buf;
   2010      1.1  haad 	const struct dm_info *info = data;
   2011      1.1  haad 
   2012      1.1  haad 	buf[0] = info->live_table ? 'L' : '-';
   2013      1.1  haad 	buf[1] = info->inactive_table ? 'I' : '-';
   2014      1.1  haad 	buf[2] = info->suspended ? 's' : '-';
   2015      1.1  haad 	buf[3] = info->read_only ? 'r' : 'w';
   2016      1.1  haad 	buf[4] = '\0';
   2017      1.1  haad 
   2018      1.1  haad 	return dm_report_field_string(rh, field, &s);
   2019      1.1  haad }
   2020      1.1  haad 
   2021      1.1  haad static int _dm_info_table_loaded_disp(struct dm_report *rh,
   2022      1.1  haad 				      struct dm_pool *mem __attribute((unused)),
   2023      1.1  haad 				      struct dm_report_field *field,
   2024      1.1  haad 				      const void *data,
   2025      1.1  haad 				      void *private __attribute((unused)))
   2026      1.1  haad {
   2027      1.1  haad 	const struct dm_info *info = data;
   2028      1.1  haad 
   2029      1.1  haad 	if (info->live_table) {
   2030      1.1  haad 		if (info->inactive_table)
   2031      1.1  haad 			dm_report_field_set_value(field, "Both", NULL);
   2032      1.1  haad 		else
   2033      1.1  haad 			dm_report_field_set_value(field, "Live", NULL);
   2034      1.1  haad 		return 1;
   2035      1.1  haad 	}
   2036      1.1  haad 
   2037      1.1  haad 	if (info->inactive_table)
   2038      1.1  haad 		dm_report_field_set_value(field, "Inactive", NULL);
   2039      1.1  haad 	else
   2040      1.1  haad 		dm_report_field_set_value(field, "None", NULL);
   2041      1.1  haad 
   2042      1.1  haad 	return 1;
   2043      1.1  haad }
   2044      1.1  haad 
   2045      1.1  haad static int _dm_info_suspended_disp(struct dm_report *rh,
   2046      1.1  haad 				   struct dm_pool *mem __attribute((unused)),
   2047      1.1  haad 				   struct dm_report_field *field,
   2048      1.1  haad 				   const void *data,
   2049      1.1  haad 				   void *private __attribute((unused)))
   2050      1.1  haad {
   2051      1.1  haad 	const struct dm_info *info = data;
   2052      1.1  haad 
   2053      1.1  haad 	if (info->suspended)
   2054      1.1  haad 		dm_report_field_set_value(field, "Suspended", NULL);
   2055      1.1  haad 	else
   2056      1.1  haad 		dm_report_field_set_value(field, "Active", NULL);
   2057      1.1  haad 
   2058      1.1  haad 	return 1;
   2059      1.1  haad }
   2060      1.1  haad 
   2061      1.1  haad static int _dm_info_read_only_disp(struct dm_report *rh,
   2062      1.1  haad 				   struct dm_pool *mem __attribute((unused)),
   2063      1.1  haad 				   struct dm_report_field *field,
   2064      1.1  haad 				   const void *data,
   2065      1.1  haad 				   void *private __attribute((unused)))
   2066      1.1  haad {
   2067      1.1  haad 	const struct dm_info *info = data;
   2068      1.1  haad 
   2069      1.1  haad 	if (info->read_only)
   2070      1.1  haad 		dm_report_field_set_value(field, "Read-only", NULL);
   2071      1.1  haad 	else
   2072      1.1  haad 		dm_report_field_set_value(field, "Writeable", NULL);
   2073      1.1  haad 
   2074      1.1  haad 	return 1;
   2075      1.1  haad }
   2076      1.1  haad 
   2077      1.1  haad 
   2078      1.1  haad static int _dm_info_devno_disp(struct dm_report *rh, struct dm_pool *mem,
   2079      1.1  haad 			       struct dm_report_field *field, const void *data,
   2080      1.1  haad 			       void *private)
   2081      1.1  haad {
   2082      1.1  haad 	char buf[DM_MAX_TYPE_NAME], *repstr;
   2083      1.1  haad 	struct dm_info *info = (struct dm_info *) data;
   2084      1.1  haad 
   2085      1.1  haad 	if (!dm_pool_begin_object(mem, 8)) {
   2086      1.1  haad 		log_error("dm_pool_begin_object failed");
   2087      1.1  haad 		return 0;
   2088      1.1  haad 	}
   2089      1.1  haad 
   2090      1.1  haad 	if (dm_snprintf(buf, sizeof(buf), "%d:%d",
   2091      1.1  haad 			info->major, info->minor) < 0) {
   2092      1.1  haad 		log_error("dm_pool_alloc failed");
   2093      1.1  haad 		goto out_abandon;
   2094      1.1  haad 	}
   2095      1.1  haad 
   2096      1.1  haad 	if (!dm_pool_grow_object(mem, buf, strlen(buf) + 1)) {
   2097      1.1  haad 		log_error("dm_pool_grow_object failed");
   2098      1.1  haad 		goto out_abandon;
   2099      1.1  haad 	}
   2100      1.1  haad 
   2101      1.1  haad 	repstr = dm_pool_end_object(mem);
   2102      1.1  haad 	dm_report_field_set_value(field, repstr, repstr);
   2103      1.1  haad 	return 1;
   2104      1.1  haad 
   2105      1.1  haad       out_abandon:
   2106      1.1  haad 	dm_pool_abandon_object(mem);
   2107      1.1  haad 	return 0;
   2108      1.1  haad }
   2109      1.1  haad 
   2110      1.1  haad static int _dm_tree_names(struct dm_report *rh, struct dm_pool *mem,
   2111      1.1  haad 			  struct dm_report_field *field, const void *data,
   2112      1.1  haad 			  void *private, unsigned inverted)
   2113      1.1  haad {
   2114      1.1  haad 	struct dm_tree_node *node = (struct dm_tree_node *) data, *parent;
   2115      1.1  haad 	void *t = NULL;
   2116      1.1  haad 	const char *name;
   2117      1.1  haad 	int first_node = 1;
   2118      1.1  haad 	char *repstr;
   2119      1.1  haad 
   2120      1.1  haad 	if (!dm_pool_begin_object(mem, 16)) {
   2121      1.1  haad 		log_error("dm_pool_begin_object failed");
   2122      1.1  haad 		return 0;
   2123      1.1  haad 	}
   2124      1.1  haad 
   2125      1.1  haad 	while ((parent = dm_tree_next_child(&t, node, inverted))) {
   2126      1.1  haad 		name = dm_tree_node_get_name(parent);
   2127      1.1  haad 		if (!name || !*name)
   2128      1.1  haad 			continue;
   2129      1.1  haad 		if (!first_node && !dm_pool_grow_object(mem, ",", 1)) {
   2130      1.1  haad 			log_error("dm_pool_grow_object failed");
   2131      1.1  haad 			goto out_abandon;
   2132      1.1  haad 		}
   2133      1.1  haad 		if (!dm_pool_grow_object(mem, name, 0)) {
   2134      1.1  haad 			log_error("dm_pool_grow_object failed");
   2135      1.1  haad 			goto out_abandon;
   2136      1.1  haad 		}
   2137      1.1  haad 		if (first_node)
   2138      1.1  haad 			first_node = 0;
   2139      1.1  haad 	}
   2140      1.1  haad 
   2141      1.1  haad 	if (!dm_pool_grow_object(mem, "\0", 1)) {
   2142      1.1  haad 		log_error("dm_pool_grow_object failed");
   2143      1.1  haad 		goto out_abandon;
   2144      1.1  haad 	}
   2145      1.1  haad 
   2146      1.1  haad 	repstr = dm_pool_end_object(mem);
   2147      1.1  haad 	dm_report_field_set_value(field, repstr, repstr);
   2148      1.1  haad 	return 1;
   2149      1.1  haad 
   2150      1.1  haad       out_abandon:
   2151      1.1  haad 	dm_pool_abandon_object(mem);
   2152      1.1  haad 	return 0;
   2153      1.1  haad }
   2154      1.1  haad 
   2155      1.1  haad static int _dm_deps_names_disp(struct dm_report *rh,
   2156      1.1  haad 				      struct dm_pool *mem,
   2157      1.1  haad 				      struct dm_report_field *field,
   2158      1.1  haad 				      const void *data, void *private)
   2159      1.1  haad {
   2160      1.1  haad 	return _dm_tree_names(rh, mem, field, data, private, 0);
   2161      1.1  haad }
   2162      1.1  haad 
   2163      1.1  haad static int _dm_tree_parents_names_disp(struct dm_report *rh,
   2164      1.1  haad 				       struct dm_pool *mem,
   2165      1.1  haad 				       struct dm_report_field *field,
   2166      1.1  haad 				       const void *data, void *private)
   2167      1.1  haad {
   2168      1.1  haad 	return _dm_tree_names(rh, mem, field, data, private, 1);
   2169      1.1  haad }
   2170      1.1  haad 
   2171      1.1  haad static int _dm_tree_parents_devs_disp(struct dm_report *rh, struct dm_pool *mem,
   2172      1.1  haad 				      struct dm_report_field *field,
   2173      1.1  haad 				      const void *data, void *private)
   2174      1.1  haad {
   2175      1.1  haad 	struct dm_tree_node *node = (struct dm_tree_node *) data, *parent;
   2176      1.1  haad 	void *t = NULL;
   2177      1.1  haad 	const struct dm_info *info;
   2178      1.1  haad 	int first_node = 1;
   2179      1.1  haad 	char buf[DM_MAX_TYPE_NAME], *repstr;
   2180      1.1  haad 
   2181      1.1  haad 	if (!dm_pool_begin_object(mem, 16)) {
   2182      1.1  haad 		log_error("dm_pool_begin_object failed");
   2183      1.1  haad 		return 0;
   2184      1.1  haad 	}
   2185      1.1  haad 
   2186      1.1  haad 	while ((parent = dm_tree_next_child(&t, node, 1))) {
   2187      1.1  haad 		info = dm_tree_node_get_info(parent);
   2188      1.1  haad 		if (!info->major && !info->minor)
   2189      1.1  haad 			continue;
   2190      1.1  haad 		if (!first_node && !dm_pool_grow_object(mem, ",", 1)) {
   2191      1.1  haad 			log_error("dm_pool_grow_object failed");
   2192      1.1  haad 			goto out_abandon;
   2193      1.1  haad 		}
   2194      1.1  haad 		if (dm_snprintf(buf, sizeof(buf), "%d:%d",
   2195      1.1  haad 				info->major, info->minor) < 0) {
   2196      1.1  haad 			log_error("dm_snprintf failed");
   2197      1.1  haad 			goto out_abandon;
   2198      1.1  haad 		}
   2199      1.1  haad 		if (!dm_pool_grow_object(mem, buf, 0)) {
   2200      1.1  haad 			log_error("dm_pool_grow_object failed");
   2201      1.1  haad 			goto out_abandon;
   2202      1.1  haad 		}
   2203      1.1  haad 		if (first_node)
   2204      1.1  haad 			first_node = 0;
   2205      1.1  haad 	}
   2206      1.1  haad 
   2207      1.1  haad 	if (!dm_pool_grow_object(mem, "\0", 1)) {
   2208      1.1  haad 		log_error("dm_pool_grow_object failed");
   2209      1.1  haad 		goto out_abandon;
   2210      1.1  haad 	}
   2211      1.1  haad 
   2212      1.1  haad 	repstr = dm_pool_end_object(mem);
   2213      1.1  haad 	dm_report_field_set_value(field, repstr, repstr);
   2214      1.1  haad 	return 1;
   2215      1.1  haad 
   2216      1.1  haad       out_abandon:
   2217      1.1  haad 	dm_pool_abandon_object(mem);
   2218      1.1  haad 	return 0;
   2219      1.1  haad }
   2220      1.1  haad 
   2221      1.1  haad static int _dm_tree_parents_count_disp(struct dm_report *rh,
   2222      1.1  haad 				       struct dm_pool *mem,
   2223      1.1  haad 				       struct dm_report_field *field,
   2224      1.1  haad 				       const void *data, void *private)
   2225      1.1  haad {
   2226      1.1  haad 	struct dm_tree_node *node = (struct dm_tree_node *) data;
   2227      1.1  haad 	int num_parent = dm_tree_node_num_children(node, 1);
   2228      1.1  haad 
   2229      1.1  haad 	return dm_report_field_int(rh, field, &num_parent);
   2230      1.1  haad }
   2231      1.1  haad 
   2232      1.1  haad static int _dm_deps_disp(struct dm_report *rh, struct dm_pool *mem,
   2233      1.1  haad 			 struct dm_report_field *field, const void *data,
   2234      1.1  haad 			 void *private)
   2235      1.1  haad {
   2236      1.1  haad 	struct dm_deps *deps = (struct dm_deps *) data;
   2237      1.1  haad 	int i;
   2238      1.1  haad 	char buf[DM_MAX_TYPE_NAME], *repstr;
   2239      1.1  haad 
   2240      1.1  haad 	if (!dm_pool_begin_object(mem, 16)) {
   2241      1.1  haad 		log_error("dm_pool_begin_object failed");
   2242      1.1  haad 		return 0;
   2243      1.1  haad 	}
   2244      1.1  haad 
   2245      1.1  haad 	for (i = 0; i < deps->count; i++) {
   2246      1.1  haad 		if (dm_snprintf(buf, sizeof(buf), "%d:%d",
   2247      1.1  haad 		       (int) MAJOR(deps->device[i]),
   2248      1.1  haad 		       (int) MINOR(deps->device[i])) < 0) {
   2249      1.1  haad 			log_error("dm_snprintf failed");
   2250      1.1  haad 			goto out_abandon;
   2251      1.1  haad 		}
   2252      1.1  haad 		if (!dm_pool_grow_object(mem, buf, 0)) {
   2253      1.1  haad 			log_error("dm_pool_grow_object failed");
   2254      1.1  haad 			goto out_abandon;
   2255      1.1  haad 		}
   2256      1.1  haad 		if (i + 1 < deps->count && !dm_pool_grow_object(mem, ",", 1)) {
   2257      1.1  haad 			log_error("dm_pool_grow_object failed");
   2258      1.1  haad 			goto out_abandon;
   2259      1.1  haad 		}
   2260      1.1  haad 	}
   2261      1.1  haad 
   2262      1.1  haad 	if (!dm_pool_grow_object(mem, "\0", 1)) {
   2263      1.1  haad 		log_error("dm_pool_grow_object failed");
   2264      1.1  haad 		goto out_abandon;
   2265      1.1  haad 	}
   2266      1.1  haad 
   2267      1.1  haad 	repstr = dm_pool_end_object(mem);
   2268      1.1  haad 	dm_report_field_set_value(field, repstr, repstr);
   2269      1.1  haad 	return 1;
   2270      1.1  haad 
   2271      1.1  haad       out_abandon:
   2272      1.1  haad 	dm_pool_abandon_object(mem);
   2273      1.1  haad 	return 0;
   2274      1.1  haad }
   2275      1.1  haad 
   2276  1.1.1.2  haad static int _dm_subsystem_disp(struct dm_report *rh,
   2277  1.1.1.2  haad 			       struct dm_pool *mem __attribute((unused)),
   2278  1.1.1.2  haad 			       struct dm_report_field *field, const void *data,
   2279  1.1.1.2  haad 			       void *private __attribute((unused)))
   2280  1.1.1.2  haad {
   2281  1.1.1.2  haad 	return dm_report_field_string(rh, field, (const char **) data);
   2282  1.1.1.2  haad }
   2283  1.1.1.2  haad 
   2284  1.1.1.2  haad static int _dm_vg_name_disp(struct dm_report *rh,
   2285  1.1.1.2  haad 			     struct dm_pool *mem __attribute((unused)),
   2286  1.1.1.2  haad 			     struct dm_report_field *field, const void *data,
   2287  1.1.1.2  haad 			     void *private __attribute((unused)))
   2288  1.1.1.2  haad {
   2289  1.1.1.2  haad 
   2290  1.1.1.2  haad 	return dm_report_field_string(rh, field, (const char **) data);
   2291  1.1.1.2  haad }
   2292  1.1.1.2  haad 
   2293  1.1.1.2  haad static int _dm_lv_name_disp(struct dm_report *rh,
   2294  1.1.1.2  haad 			     struct dm_pool *mem __attribute((unused)),
   2295  1.1.1.2  haad 			     struct dm_report_field *field, const void *data,
   2296  1.1.1.2  haad 			     void *private __attribute((unused)))
   2297  1.1.1.2  haad 
   2298  1.1.1.2  haad {
   2299  1.1.1.2  haad 	return dm_report_field_string(rh, field, (const char **) data);
   2300  1.1.1.2  haad }
   2301  1.1.1.2  haad 
   2302  1.1.1.2  haad static int _dm_lv_layer_name_disp(struct dm_report *rh,
   2303  1.1.1.2  haad 				   struct dm_pool *mem __attribute((unused)),
   2304  1.1.1.2  haad 				   struct dm_report_field *field, const void *data,
   2305  1.1.1.2  haad 				   void *private __attribute((unused)))
   2306  1.1.1.2  haad 
   2307  1.1.1.2  haad {
   2308  1.1.1.2  haad 	return dm_report_field_string(rh, field, (const char **) data);
   2309  1.1.1.2  haad }
   2310  1.1.1.2  haad 
   2311      1.1  haad static void *_task_get_obj(void *obj)
   2312      1.1  haad {
   2313      1.1  haad 	return ((struct dmsetup_report_obj *)obj)->task;
   2314      1.1  haad }
   2315      1.1  haad 
   2316      1.1  haad static void *_info_get_obj(void *obj)
   2317      1.1  haad {
   2318      1.1  haad 	return ((struct dmsetup_report_obj *)obj)->info;
   2319      1.1  haad }
   2320      1.1  haad 
   2321      1.1  haad static void *_deps_get_obj(void *obj)
   2322      1.1  haad {
   2323      1.1  haad 	return dm_task_get_deps(((struct dmsetup_report_obj *)obj)->deps_task);
   2324      1.1  haad }
   2325      1.1  haad 
   2326      1.1  haad static void *_tree_get_obj(void *obj)
   2327      1.1  haad {
   2328      1.1  haad 	return ((struct dmsetup_report_obj *)obj)->tree_node;
   2329      1.1  haad }
   2330      1.1  haad 
   2331  1.1.1.2  haad static void *_split_name_get_obj(void *obj)
   2332  1.1.1.2  haad {
   2333  1.1.1.2  haad 	return ((struct dmsetup_report_obj *)obj)->split_name;
   2334  1.1.1.2  haad }
   2335  1.1.1.2  haad 
   2336      1.1  haad static const struct dm_report_object_type _report_types[] = {
   2337      1.1  haad 	{ DR_TASK, "Mapped Device Name", "", _task_get_obj },
   2338      1.1  haad 	{ DR_INFO, "Mapped Device Information", "", _info_get_obj },
   2339      1.1  haad 	{ DR_DEPS, "Mapped Device Relationship Information", "", _deps_get_obj },
   2340      1.1  haad 	{ DR_TREE, "Mapped Device Relationship Information", "", _tree_get_obj },
   2341  1.1.1.2  haad 	{ DR_NAME, "Mapped Device Name Components", "", _split_name_get_obj },
   2342      1.1  haad 	{ 0, "", "", NULL },
   2343      1.1  haad };
   2344      1.1  haad 
   2345      1.1  haad /* Column definitions */
   2346      1.1  haad #define OFFSET_OF(strct, field) (((char*)&((struct strct*)0)->field) - (char*)0)
   2347      1.1  haad #define STR (DM_REPORT_FIELD_TYPE_STRING)
   2348      1.1  haad #define NUM (DM_REPORT_FIELD_TYPE_NUMBER)
   2349      1.1  haad #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},
   2350      1.1  haad #define FIELD_F(type, sorttype, head, width, func, id, desc) {DR_ ## type, sorttype, 0, width, id, head, &_ ## func ## _disp, desc},
   2351      1.1  haad 
   2352      1.1  haad static const struct dm_report_field_type _report_fields[] = {
   2353      1.1  haad /* *INDENT-OFF* */
   2354      1.1  haad FIELD_F(TASK, STR, "Name", 16, dm_name, "name", "Name of mapped device.")
   2355      1.1  haad FIELD_F(TASK, STR, "UUID", 32, dm_uuid, "uuid", "Unique (optional) identifier for mapped device.")
   2356      1.1  haad 
   2357      1.1  haad /* FIXME Next one should be INFO */
   2358      1.1  haad FIELD_F(TASK, NUM, "RAhead", 6, dm_read_ahead, "read_ahead", "Read ahead in sectors.")
   2359      1.1  haad 
   2360      1.1  haad FIELD_F(INFO, STR, "Stat", 4, dm_info_status, "attr", "(L)ive, (I)nactive, (s)uspended, (r)ead-only, read-(w)rite.")
   2361      1.1  haad FIELD_F(INFO, STR, "Tables", 6, dm_info_table_loaded, "tables_loaded", "Which of the live and inactive table slots are filled.")
   2362      1.1  haad FIELD_F(INFO, STR, "Suspended", 9, dm_info_suspended, "suspended", "Whether the device is suspended.")
   2363      1.1  haad FIELD_F(INFO, STR, "Read-only", 9, dm_info_read_only, "readonly", "Whether the device is read-only or writeable.")
   2364      1.1  haad FIELD_F(INFO, STR, "DevNo", 5, dm_info_devno, "devno", "Device major and minor numbers")
   2365      1.1  haad FIELD_O(INFO, dm_info, NUM, "Maj", major, 3, int32, "major", "Block device major number.")
   2366      1.1  haad FIELD_O(INFO, dm_info, NUM, "Min", minor, 3, int32, "minor", "Block device minor number.")
   2367      1.1  haad FIELD_O(INFO, dm_info, NUM, "Open", open_count, 4, int32, "open", "Number of references to open device, if requested.")
   2368      1.1  haad FIELD_O(INFO, dm_info, NUM, "Targ", target_count, 4, int32, "segments", "Number of segments in live table, if present.")
   2369      1.1  haad FIELD_O(INFO, dm_info, NUM, "Event", event_nr, 6, uint32, "events", "Number of most recent event.")
   2370      1.1  haad 
   2371      1.1  haad FIELD_O(DEPS, dm_deps, NUM, "#Devs", count, 5, int32, "device_count", "Number of devices used by this one.")
   2372      1.1  haad FIELD_F(TREE, STR, "DevNames", 8, dm_deps_names, "devs_used", "List of names of mapped devices used by this one.")
   2373      1.1  haad FIELD_F(DEPS, STR, "DevNos", 6, dm_deps, "devnos_used", "List of device numbers of devices used by this one.")
   2374      1.1  haad 
   2375      1.1  haad FIELD_F(TREE, NUM, "#Refs", 5, dm_tree_parents_count, "device_ref_count", "Number of mapped devices referencing this one.")
   2376      1.1  haad FIELD_F(TREE, STR, "RefNames", 8, dm_tree_parents_names, "names_using_dev", "List of names of mapped devices using this one.")
   2377      1.1  haad FIELD_F(TREE, STR, "RefDevNos", 9, dm_tree_parents_devs, "devnos_using_dev", "List of device numbers of mapped devices using this one.")
   2378  1.1.1.2  haad 
   2379  1.1.1.2  haad FIELD_O(NAME, dm_split_name, STR, "Subsys", subsystem, 6, dm_subsystem, "subsystem", "Userspace subsystem responsible for this device.")
   2380  1.1.1.2  haad FIELD_O(NAME, dm_split_name, STR, "VG", vg_name, 4, dm_vg_name, "vg_name", "LVM Volume Group name.")
   2381  1.1.1.2  haad FIELD_O(NAME, dm_split_name, STR, "LV", lv_name, 4, dm_lv_name, "lv_name", "LVM Logical Volume name.")
   2382  1.1.1.2  haad FIELD_O(NAME, dm_split_name, STR, "LVLayer", lv_layer, 7, dm_lv_layer_name, "lv_layer", "LVM device layer.")
   2383  1.1.1.2  haad 
   2384      1.1  haad {0, 0, 0, 0, "", "", NULL, NULL},
   2385      1.1  haad /* *INDENT-ON* */
   2386      1.1  haad };
   2387      1.1  haad 
   2388      1.1  haad #undef STR
   2389      1.1  haad #undef NUM
   2390      1.1  haad #undef FIELD_O
   2391      1.1  haad #undef FIELD_F
   2392      1.1  haad 
   2393      1.1  haad static const char *default_report_options = "name,major,minor,attr,open,segments,events,uuid";
   2394  1.1.1.2  haad static const char *splitname_report_options = "vg_name,lv_name,lv_layer";
   2395      1.1  haad 
   2396      1.1  haad static int _report_init(struct command *c)
   2397      1.1  haad {
   2398      1.1  haad 	char *options = (char *) default_report_options;
   2399      1.1  haad 	const char *keys = "";
   2400      1.1  haad 	const char *separator = " ";
   2401      1.1  haad 	int aligned = 1, headings = 1, buffered = 1, field_prefixes = 0;
   2402      1.1  haad 	int quoted = 1, columns_as_rows = 0;
   2403      1.1  haad 	uint32_t flags = 0;
   2404      1.1  haad 	size_t len = 0;
   2405      1.1  haad 	int r = 0;
   2406      1.1  haad 
   2407  1.1.1.2  haad 	if (!strcmp(c->name, "splitname"))
   2408  1.1.1.2  haad 		options = (char *) splitname_report_options;
   2409  1.1.1.2  haad 
   2410      1.1  haad 	/* emulate old dmsetup behaviour */
   2411      1.1  haad 	if (_switches[NOHEADINGS_ARG]) {
   2412      1.1  haad 		separator = ":";
   2413      1.1  haad 		aligned = 0;
   2414      1.1  haad 		headings = 0;
   2415      1.1  haad 	}
   2416      1.1  haad 
   2417      1.1  haad 	if (_switches[UNBUFFERED_ARG])
   2418      1.1  haad 		buffered = 0;
   2419      1.1  haad 
   2420      1.1  haad 	if (_switches[ROWS_ARG])
   2421      1.1  haad 		columns_as_rows = 1;
   2422      1.1  haad 
   2423      1.1  haad 	if (_switches[UNQUOTED_ARG])
   2424      1.1  haad 		quoted = 0;
   2425      1.1  haad 
   2426      1.1  haad 	if (_switches[NAMEPREFIXES_ARG]) {
   2427      1.1  haad 		aligned = 0;
   2428      1.1  haad 		field_prefixes = 1;
   2429      1.1  haad 	}
   2430      1.1  haad 
   2431      1.1  haad 	if (_switches[OPTIONS_ARG] && _string_args[OPTIONS_ARG]) {
   2432      1.1  haad 		if (*_string_args[OPTIONS_ARG] != '+')
   2433      1.1  haad 			options = _string_args[OPTIONS_ARG];
   2434      1.1  haad 		else {
   2435      1.1  haad 			len = strlen(default_report_options) +
   2436      1.1  haad 			      strlen(_string_args[OPTIONS_ARG]) + 1;
   2437      1.1  haad 			if (!(options = dm_malloc(len))) {
   2438      1.1  haad 				err("Failed to allocate option string.");
   2439      1.1  haad 				return 0;
   2440      1.1  haad 			}
   2441      1.1  haad 			if (dm_snprintf(options, len, "%s,%s",
   2442      1.1  haad 					default_report_options,
   2443      1.1  haad 					&_string_args[OPTIONS_ARG][1]) < 0) {
   2444      1.1  haad 				err("snprintf failed");
   2445      1.1  haad 				goto out;
   2446      1.1  haad 			}
   2447      1.1  haad 		}
   2448      1.1  haad 	}
   2449      1.1  haad 
   2450      1.1  haad 	if (_switches[SORT_ARG] && _string_args[SORT_ARG]) {
   2451      1.1  haad 		keys = _string_args[SORT_ARG];
   2452      1.1  haad 		buffered = 1;
   2453      1.1  haad 		if (c && (!strcmp(c->name, "status") || !strcmp(c->name, "table"))) {
   2454      1.1  haad 			err("--sort is not yet supported with status and table");
   2455      1.1  haad 			goto out;
   2456      1.1  haad 		}
   2457      1.1  haad 	}
   2458      1.1  haad 
   2459      1.1  haad 	if (_switches[SEPARATOR_ARG] && _string_args[SEPARATOR_ARG]) {
   2460      1.1  haad 		separator = _string_args[SEPARATOR_ARG];
   2461      1.1  haad 		aligned = 0;
   2462      1.1  haad 	}
   2463      1.1  haad 
   2464      1.1  haad 	if (aligned)
   2465      1.1  haad 		flags |= DM_REPORT_OUTPUT_ALIGNED;
   2466      1.1  haad 
   2467      1.1  haad 	if (buffered)
   2468      1.1  haad 		flags |= DM_REPORT_OUTPUT_BUFFERED;
   2469      1.1  haad 
   2470      1.1  haad 	if (headings)
   2471      1.1  haad 		flags |= DM_REPORT_OUTPUT_HEADINGS;
   2472      1.1  haad 
   2473      1.1  haad 	if (field_prefixes)
   2474      1.1  haad 		flags |= DM_REPORT_OUTPUT_FIELD_NAME_PREFIX;
   2475      1.1  haad 
   2476      1.1  haad 	if (!quoted)
   2477      1.1  haad 		flags |= DM_REPORT_OUTPUT_FIELD_UNQUOTED;
   2478      1.1  haad 
   2479      1.1  haad 	if (columns_as_rows)
   2480      1.1  haad 		flags |= DM_REPORT_OUTPUT_COLUMNS_AS_ROWS;
   2481      1.1  haad 
   2482      1.1  haad 	if (!(_report = dm_report_init(&_report_type,
   2483      1.1  haad 				       _report_types, _report_fields,
   2484      1.1  haad 				       options, separator, flags, keys, NULL)))
   2485      1.1  haad 		goto out;
   2486      1.1  haad 
   2487      1.1  haad 	if ((_report_type & DR_TREE) && !_build_whole_deptree()) {
   2488      1.1  haad 		err("Internal device dependency tree creation failed.");
   2489      1.1  haad 		goto out;
   2490      1.1  haad 	}
   2491      1.1  haad 
   2492      1.1  haad 	if (field_prefixes)
   2493      1.1  haad 		dm_report_set_output_field_name_prefix(_report, "dm_");
   2494      1.1  haad 
   2495      1.1  haad 	r = 1;
   2496      1.1  haad 
   2497      1.1  haad out:
   2498      1.1  haad 	if (len)
   2499      1.1  haad 		dm_free(options);
   2500      1.1  haad 
   2501      1.1  haad 	return r;
   2502      1.1  haad }
   2503      1.1  haad 
   2504      1.1  haad /*
   2505      1.1  haad  * List devices
   2506      1.1  haad  */
   2507      1.1  haad static int _ls(int argc, char **argv, void *data)
   2508      1.1  haad {
   2509      1.1  haad 	if ((_switches[TARGET_ARG] && _target) ||
   2510      1.1  haad 	    (_switches[EXEC_ARG] && _command))
   2511      1.1  haad 		return _status(argc, argv, data);
   2512      1.1  haad 	else if ((_switches[TREE_ARG]))
   2513      1.1  haad 		return _display_tree(argc, argv, data);
   2514      1.1  haad 	else
   2515      1.1  haad 		return _process_all(argc, argv, 0, _display_name);
   2516      1.1  haad }
   2517      1.1  haad 
   2518      1.1  haad static int _help(int argc, char **argv, void *data);
   2519      1.1  haad 
   2520      1.1  haad /*
   2521      1.1  haad  * Dispatch table
   2522      1.1  haad  */
   2523      1.1  haad static struct command _commands[] = {
   2524      1.1  haad 	{"help", "[-c|-C|--columns]", 0, 0, _help},
   2525      1.1  haad 	{"create", "<dev_name> [-j|--major <major> -m|--minor <minor>]\n"
   2526      1.1  haad 	  "\t                  [-U|--uid <uid>] [-G|--gid <gid>] [-M|--mode <octal_mode>]\n"
   2527      1.1  haad 	  "\t                  [-u|uuid <uuid>]\n"
   2528      1.1  haad 	  "\t                  [--notable | --table <table> | <table_file>]",
   2529      1.1  haad 	 1, 2, _create},
   2530      1.1  haad 	{"remove", "[-f|--force] <device>", 0, 1, _remove},
   2531      1.1  haad 	{"remove_all", "[-f|--force]", 0, 0, _remove_all},
   2532      1.1  haad 	{"suspend", "[--noflush] <device>", 0, 1, _suspend},
   2533      1.1  haad 	{"resume", "<device>", 0, 1, _resume},
   2534      1.1  haad 	{"load", "<device> [<table_file>]", 0, 2, _load},
   2535      1.1  haad 	{"clear", "<device>", 0, 1, _clear},
   2536      1.1  haad 	{"reload", "<device> [<table_file>]", 0, 2, _load},
   2537      1.1  haad 	{"rename", "<device> <new_name>", 1, 2, _rename},
   2538      1.1  haad 	{"message", "<device> <sector> <message>", 2, -1, _message},
   2539      1.1  haad 	{"ls", "[--target <target_type>] [--exec <command>] [--tree [-o options]]", 0, 0, _ls},
   2540      1.1  haad 	{"info", "[<device>]", 0, 1, _info},
   2541      1.1  haad 	{"deps", "[<device>]", 0, 1, _deps},
   2542      1.1  haad 	{"status", "[<device>] [--target <target_type>]", 0, 1, _status},
   2543      1.1  haad 	{"table", "[<device>] [--target <target_type>] [--showkeys]", 0, 1, _status},
   2544      1.1  haad 	{"wait", "<device> [<event_nr>]", 0, 2, _wait},
   2545      1.1  haad 	{"mknodes", "[<device>]", 0, 1, _mknodes},
   2546  1.1.1.2  haad 	{"udevflags", "<cookie>", 1, 1, _udevflags},
   2547  1.1.1.2  haad 	{"udevcomplete", "<cookie>", 1, 1, _udevcomplete},
   2548  1.1.1.2  haad 	{"udevcomplete_all", "", 0, 0, _udevcomplete_all},
   2549  1.1.1.2  haad 	{"udevcookies", "", 0, 0, _udevcookies},
   2550      1.1  haad 	{"targets", "", 0, 0, _targets},
   2551      1.1  haad 	{"version", "", 0, 0, _version},
   2552      1.1  haad 	{"setgeometry", "<device> <cyl> <head> <sect> <start>", 5, 5, _setgeometry},
   2553  1.1.1.2  haad 	{"splitname", "<device> [<subsystem>]", 1, 2, _splitname},
   2554      1.1  haad 	{NULL, NULL, 0, 0, NULL}
   2555      1.1  haad };
   2556      1.1  haad 
   2557      1.1  haad static void _usage(FILE *out)
   2558      1.1  haad {
   2559      1.1  haad 	int i;
   2560      1.1  haad 
   2561      1.1  haad 	fprintf(out, "Usage:\n\n");
   2562      1.1  haad 	fprintf(out, "dmsetup [--version] [-v|--verbose [-v|--verbose ...]]\n"
   2563  1.1.1.2  haad 		"        [-r|--readonly] [--noopencount] [--nolockfs] [--inactive]\n"
   2564  1.1.1.2  haad 		"        [--noudevsync] [-y|--yes] [--readahead [+]<sectors>|auto|none]\n"
   2565      1.1  haad 		"        [-c|-C|--columns] [-o <fields>] [-O|--sort <sort_fields>]\n"
   2566      1.1  haad 		"        [--nameprefixes] [--noheadings] [--separator <separator>]\n\n");
   2567      1.1  haad 	for (i = 0; _commands[i].name; i++)
   2568      1.1  haad 		fprintf(out, "\t%s %s\n", _commands[i].name, _commands[i].help);
   2569      1.1  haad 	fprintf(out, "\n<device> may be device name or -u <uuid> or "
   2570      1.1  haad 		     "-j <major> -m <minor>\n");
   2571      1.1  haad 	fprintf(out, "<fields> are comma-separated.  Use 'help -c' for list.\n");
   2572      1.1  haad 	fprintf(out, "Table_file contents may be supplied on stdin.\n");
   2573      1.1  haad 	fprintf(out, "Tree options are: ascii, utf, vt100; compact, inverted, notrunc;\n"
   2574      1.1  haad 		     "                  [no]device, active, open, rw and uuid.\n");
   2575      1.1  haad 	fprintf(out, "\n");
   2576      1.1  haad 	return;
   2577      1.1  haad }
   2578      1.1  haad 
   2579      1.1  haad static void _losetup_usage(FILE *out)
   2580      1.1  haad {
   2581      1.1  haad 	fprintf(out, "Usage:\n\n");
   2582      1.1  haad 	fprintf(out, "losetup [-d|-a] [-e encryption] "
   2583      1.1  haad 		     "[-o offset] [-f|loop_device] [file]\n\n");
   2584      1.1  haad }
   2585      1.1  haad 
   2586      1.1  haad static int _help(int argc __attribute((unused)),
   2587      1.1  haad 		 char **argv __attribute((unused)),
   2588      1.1  haad 		 void *data __attribute((unused)))
   2589      1.1  haad {
   2590      1.1  haad 	_usage(stderr);
   2591      1.1  haad 
   2592      1.1  haad 	if (_switches[COLS_ARG]) {
   2593      1.1  haad 		_switches[OPTIONS_ARG] = 1;
   2594      1.1  haad 		_string_args[OPTIONS_ARG] = (char *) "help";
   2595      1.1  haad 		_switches[SORT_ARG] = 0;
   2596      1.1  haad 
   2597      1.1  haad 		(void) _report_init(NULL);
   2598      1.1  haad 	}
   2599      1.1  haad 
   2600      1.1  haad 	return 1;
   2601      1.1  haad }
   2602      1.1  haad 
   2603      1.1  haad static struct command *_find_command(const char *name)
   2604      1.1  haad {
   2605      1.1  haad 	int i;
   2606      1.1  haad 
   2607      1.1  haad 	for (i = 0; _commands[i].name; i++)
   2608      1.1  haad 		if (!strcmp(_commands[i].name, name))
   2609      1.1  haad 			return _commands + i;
   2610      1.1  haad 
   2611      1.1  haad 	return NULL;
   2612      1.1  haad }
   2613      1.1  haad 
   2614      1.1  haad static int _process_tree_options(const char *options)
   2615      1.1  haad {
   2616      1.1  haad 	const char *s, *end;
   2617      1.1  haad 	struct winsize winsz;
   2618      1.1  haad 	size_t len;
   2619      1.1  haad 
   2620      1.1  haad 	/* Symbol set default */
   2621      1.1  haad 	if (!strcmp(nl_langinfo(CODESET), "UTF-8"))
   2622      1.1  haad 		_tsym = &_tsym_utf;
   2623      1.1  haad 	else
   2624      1.1  haad 		_tsym = &_tsym_ascii;
   2625      1.1  haad 
   2626      1.1  haad 	/* Default */
   2627      1.1  haad 	_tree_switches[TR_DEVICE] = 1;
   2628      1.1  haad 	_tree_switches[TR_TRUNCATE] = 1;
   2629      1.1  haad 
   2630      1.1  haad 	/* parse */
   2631      1.1  haad 	for (s = options; s && *s; s++) {
   2632      1.1  haad 		len = 0;
   2633      1.1  haad 		for (end = s; *end && *end != ','; end++, len++)
   2634      1.1  haad 			;
   2635      1.1  haad 		if (!strncmp(s, "device", len))
   2636      1.1  haad 			_tree_switches[TR_DEVICE] = 1;
   2637      1.1  haad 		else if (!strncmp(s, "nodevice", len))
   2638      1.1  haad 			_tree_switches[TR_DEVICE] = 0;
   2639      1.1  haad 		else if (!strncmp(s, "status", len))
   2640      1.1  haad 			_tree_switches[TR_STATUS] = 1;
   2641      1.1  haad 		else if (!strncmp(s, "table", len))
   2642      1.1  haad 			_tree_switches[TR_TABLE] = 1;
   2643      1.1  haad 		else if (!strncmp(s, "active", len))
   2644      1.1  haad 			_tree_switches[TR_ACTIVE] = 1;
   2645      1.1  haad 		else if (!strncmp(s, "open", len))
   2646      1.1  haad 			_tree_switches[TR_OPENCOUNT] = 1;
   2647      1.1  haad 		else if (!strncmp(s, "uuid", len))
   2648      1.1  haad 			_tree_switches[TR_UUID] = 1;
   2649      1.1  haad 		else if (!strncmp(s, "rw", len))
   2650      1.1  haad 			_tree_switches[TR_RW] = 1;
   2651      1.1  haad 		else if (!strncmp(s, "utf", len))
   2652      1.1  haad 			_tsym = &_tsym_utf;
   2653      1.1  haad 		else if (!strncmp(s, "vt100", len))
   2654      1.1  haad 			_tsym = &_tsym_vt100;
   2655      1.1  haad 		else if (!strncmp(s, "ascii", len))
   2656      1.1  haad 			_tsym = &_tsym_ascii;
   2657      1.1  haad 		else if (!strncmp(s, "inverted", len))
   2658      1.1  haad 			_tree_switches[TR_BOTTOMUP] = 1;
   2659      1.1  haad 		else if (!strncmp(s, "compact", len))
   2660      1.1  haad 			_tree_switches[TR_COMPACT] = 1;
   2661      1.1  haad 		else if (!strncmp(s, "notrunc", len))
   2662      1.1  haad 			_tree_switches[TR_TRUNCATE] = 0;
   2663      1.1  haad 		else {
   2664      1.1  haad 			fprintf(stderr, "Tree options not recognised: %s\n", s);
   2665      1.1  haad 			return 0;
   2666      1.1  haad 		}
   2667      1.1  haad 		if (!*end)
   2668      1.1  haad 			break;
   2669      1.1  haad 		s = end;
   2670      1.1  haad 	}
   2671      1.1  haad 
   2672      1.1  haad 	/* Truncation doesn't work well with vt100 drawing char */
   2673      1.1  haad 	if (_tsym != &_tsym_vt100)
   2674      1.1  haad 		if (ioctl(1, (unsigned long) TIOCGWINSZ, &winsz) >= 0 && winsz.ws_col > 3)
   2675      1.1  haad 			_termwidth = winsz.ws_col - 3;
   2676      1.1  haad 
   2677      1.1  haad 	return 1;
   2678      1.1  haad }
   2679      1.1  haad 
   2680      1.1  haad /*
   2681      1.1  haad  * Returns the full absolute path, or NULL if the path could
   2682      1.1  haad  * not be resolved.
   2683      1.1  haad  */
   2684      1.1  haad static char *_get_abspath(const char *path)
   2685      1.1  haad {
   2686      1.1  haad 	char *_path;
   2687      1.1  haad 
   2688      1.1  haad #ifdef HAVE_CANONICALIZE_FILE_NAME
   2689      1.1  haad 	_path = canonicalize_file_name(path);
   2690      1.1  haad #else
   2691      1.1  haad 	/* FIXME Provide alternative */
   2692      1.1  haad #endif
   2693      1.1  haad 	return _path;
   2694      1.1  haad }
   2695      1.1  haad 
   2696      1.1  haad static char *parse_loop_device_name(const char *dev, const char *dev_dir)
   2697      1.1  haad {
   2698      1.1  haad 	char *buf;
   2699      1.1  haad 	char *device;
   2700      1.1  haad 
   2701      1.1  haad 	if (!(buf = dm_malloc(PATH_MAX)))
   2702      1.1  haad 		return NULL;
   2703      1.1  haad 
   2704      1.1  haad 	if (dev[0] == '/') {
   2705      1.1  haad 		if (!(device = _get_abspath(dev)))
   2706      1.1  haad 			goto error;
   2707      1.1  haad 
   2708      1.1  haad 		if (strncmp(device, dev_dir, strlen(dev_dir)))
   2709      1.1  haad 			goto error;
   2710      1.1  haad 
   2711      1.1  haad 		/* If dev_dir does not end in a slash, ensure that the
   2712      1.1  haad 		   following byte in the device string is "/".  */
   2713      1.1  haad 		if (dev_dir[strlen(dev_dir) - 1] != '/' &&
   2714      1.1  haad 		    device[strlen(dev_dir)] != '/')
   2715      1.1  haad 			goto error;
   2716      1.1  haad 
   2717      1.1  haad 		strncpy(buf, strrchr(device, '/') + 1, (size_t) PATH_MAX);
   2718      1.1  haad 		dm_free(device);
   2719      1.1  haad 
   2720      1.1  haad 	} else {
   2721      1.1  haad 		/* check for device number */
   2722      1.1  haad 		if (!strncmp(dev, "loop", strlen("loop")))
   2723      1.1  haad 			strncpy(buf, dev, (size_t) PATH_MAX);
   2724      1.1  haad 		else
   2725      1.1  haad 			goto error;
   2726      1.1  haad 	}
   2727      1.1  haad 
   2728      1.1  haad 	return buf;
   2729      1.1  haad 
   2730      1.1  haad error:
   2731      1.1  haad 	return NULL;
   2732      1.1  haad }
   2733      1.1  haad 
   2734      1.1  haad /*
   2735      1.1  haad  *  create a table for a mapped device using the loop target.
   2736      1.1  haad  */
   2737      1.1  haad static int _loop_table(char *table, size_t tlen, char *file,
   2738      1.1  haad 		       char *dev __attribute((unused)), off_t off)
   2739      1.1  haad {
   2740      1.1  haad 	struct stat fbuf;
   2741      1.1  haad 	off_t size, sectors;
   2742      1.1  haad 	int fd = -1;
   2743      1.1  haad #ifdef HAVE_SYS_STATVFS_H
   2744      1.1  haad 	struct statvfs fsbuf;
   2745      1.1  haad 	off_t blksize;
   2746      1.1  haad #endif
   2747      1.1  haad 
   2748      1.1  haad 	if (!_switches[READ_ONLY])
   2749      1.1  haad 		fd = open(file, O_RDWR);
   2750      1.1  haad 
   2751      1.1  haad 	if (fd < 0) {
   2752      1.1  haad 		_switches[READ_ONLY]++;
   2753      1.1  haad 		fd = open(file, O_RDONLY);
   2754      1.1  haad 	}
   2755      1.1  haad 
   2756      1.1  haad 	if (fd < 0)
   2757      1.1  haad 		goto error;
   2758      1.1  haad 
   2759      1.1  haad 	if (fstat(fd, &fbuf))
   2760      1.1  haad 		goto error;
   2761      1.1  haad 
   2762      1.1  haad 	size = (fbuf.st_size - off);
   2763      1.1  haad 	sectors = size >> SECTOR_SHIFT;
   2764      1.1  haad 
   2765      1.1  haad 	if (_switches[VERBOSE_ARG])
   2766      1.1  haad 		fprintf(stderr, "losetup: set loop size to %llukB "
   2767      1.1  haad 			"(%llu sectors)\n", (long long unsigned) sectors >> 1,
   2768      1.1  haad 			(long long unsigned) sectors);
   2769      1.1  haad 
   2770      1.1  haad #ifdef HAVE_SYS_STATVFS_H
   2771      1.1  haad 	if (fstatvfs(fd, &fsbuf))
   2772      1.1  haad 		goto error;
   2773      1.1  haad 
   2774      1.1  haad 	/* FIXME Fragment size currently unused */
   2775      1.1  haad 	blksize = fsbuf.f_frsize;
   2776      1.1  haad #endif
   2777      1.1  haad 
   2778      1.1  haad 	close(fd);
   2779      1.1  haad 
   2780      1.1  haad 	if (dm_snprintf(table, tlen, "%llu %llu loop %s %llu\n", 0ULL,
   2781      1.1  haad 			(long long unsigned)sectors, file, off) < 0)
   2782      1.1  haad 		return 0;
   2783      1.1  haad 
   2784      1.1  haad 	if (_switches[VERBOSE_ARG] > 1)
   2785      1.1  haad 		fprintf(stderr, "Table: %s\n", table);
   2786      1.1  haad 
   2787      1.1  haad 	return 1;
   2788      1.1  haad 
   2789      1.1  haad error:
   2790      1.1  haad 	if (fd > -1)
   2791      1.1  haad 		close(fd);
   2792      1.1  haad 	return 0;
   2793      1.1  haad }
   2794      1.1  haad 
   2795      1.1  haad static int _process_losetup_switches(const char *base, int *argc, char ***argv,
   2796      1.1  haad 				     const char *dev_dir)
   2797      1.1  haad {
   2798      1.1  haad 	static int ind;
   2799      1.1  haad 	int c;
   2800      1.1  haad 	int encrypt_loop = 0, delete = 0, find = 0, show_all = 0;
   2801      1.1  haad 	char *device_name = NULL;
   2802      1.1  haad 	char *loop_file = NULL;
   2803      1.1  haad 	off_t offset = 0;
   2804      1.1  haad 
   2805      1.1  haad #ifdef HAVE_GETOPTLONG
   2806      1.1  haad 	static struct option long_options[] = {
   2807      1.1  haad 		{0, 0, 0, 0}
   2808      1.1  haad 	};
   2809      1.1  haad #endif
   2810      1.1  haad 
   2811      1.1  haad 	optarg = 0;
   2812      1.1  haad 	optind = OPTIND_INIT;
   2813      1.1  haad 	while ((ind = -1, c = GETOPTLONG_FN(*argc, *argv, "ade:fo:v",
   2814      1.1  haad 					    long_options, NULL)) != -1 ) {
   2815      1.1  haad 		if (c == ':' || c == '?')
   2816      1.1  haad 			return 0;
   2817      1.1  haad 		if (c == 'a')
   2818      1.1  haad 			show_all++;
   2819      1.1  haad 		if (c == 'd')
   2820      1.1  haad 			delete++;
   2821      1.1  haad 		if (c == 'e')
   2822      1.1  haad 			encrypt_loop++;
   2823      1.1  haad 		if (c == 'f')
   2824      1.1  haad 			find++;
   2825      1.1  haad 		if (c == 'o')
   2826      1.1  haad 			offset = atoi(optarg);
   2827      1.1  haad 		if (c == 'v')
   2828      1.1  haad 			_switches[VERBOSE_ARG]++;
   2829      1.1  haad 	}
   2830      1.1  haad 
   2831      1.1  haad 	*argv += optind ;
   2832      1.1  haad 	*argc -= optind ;
   2833      1.1  haad 
   2834      1.1  haad 	if (encrypt_loop){
   2835      1.1  haad 		fprintf(stderr, "%s: Sorry, cryptoloop is not yet implemented "
   2836      1.1  haad 				"in this version.\n", base);
   2837      1.1  haad 		return 0;
   2838      1.1  haad 	}
   2839      1.1  haad 
   2840      1.1  haad 	if (show_all) {
   2841      1.1  haad 		fprintf(stderr, "%s: Sorry, show all is not yet implemented "
   2842      1.1  haad 				"in this version.\n", base);
   2843      1.1  haad 		return 0;
   2844      1.1  haad 	}
   2845      1.1  haad 
   2846      1.1  haad 	if (find) {
   2847      1.1  haad 		fprintf(stderr, "%s: Sorry, find is not yet implemented "
   2848      1.1  haad 				"in this version.\n", base);
   2849      1.1  haad 		if (!*argc)
   2850      1.1  haad 			return 0;
   2851      1.1  haad 	}
   2852      1.1  haad 
   2853      1.1  haad 	if (!*argc) {
   2854      1.1  haad 		fprintf(stderr, "%s: Please specify loop_device.\n", base);
   2855      1.1  haad 		_losetup_usage(stderr);
   2856      1.1  haad 		return 0;
   2857      1.1  haad 	}
   2858      1.1  haad 
   2859      1.1  haad 	if (!(device_name = parse_loop_device_name((*argv)[0], dev_dir))) {
   2860      1.1  haad 		fprintf(stderr, "%s: Could not parse loop_device %s\n",
   2861      1.1  haad 			base, (*argv)[0]);
   2862      1.1  haad 		_losetup_usage(stderr);
   2863      1.1  haad 		return 0;
   2864      1.1  haad 	}
   2865      1.1  haad 
   2866      1.1  haad 	if (delete) {
   2867      1.1  haad 		*argc = 2;
   2868      1.1  haad 
   2869      1.1  haad 		(*argv)[1] = device_name;
   2870      1.1  haad 		(*argv)[0] = (char *) "remove";
   2871      1.1  haad 
   2872      1.1  haad 		return 1;
   2873      1.1  haad 	}
   2874      1.1  haad 
   2875      1.1  haad 	if (*argc != 2) {
   2876      1.1  haad 		fprintf(stderr, "%s: Too few arguments\n", base);
   2877      1.1  haad 		_losetup_usage(stderr);
   2878      1.1  haad 		dm_free(device_name);
   2879      1.1  haad 		return 0;
   2880      1.1  haad 	}
   2881      1.1  haad 
   2882      1.1  haad 	/* FIXME move these to make them available to native dmsetup */
   2883      1.1  haad 	if (!(loop_file = _get_abspath((*argv)[(find) ? 0 : 1]))) {
   2884      1.1  haad 		fprintf(stderr, "%s: Could not parse loop file name %s\n",
   2885      1.1  haad 			base, (*argv)[1]);
   2886      1.1  haad 		_losetup_usage(stderr);
   2887      1.1  haad 		dm_free(device_name);
   2888      1.1  haad 		return 0;
   2889      1.1  haad 	}
   2890      1.1  haad 
   2891      1.1  haad 	/* FIXME Missing free */
   2892      1.1  haad 	_table = dm_malloc(LOOP_TABLE_SIZE);
   2893      1.1  haad 	if (!_loop_table(_table, (size_t) LOOP_TABLE_SIZE, loop_file, device_name, offset)) {
   2894      1.1  haad 		fprintf(stderr, "Could not build device-mapper table for %s\n", (*argv)[0]);
   2895      1.1  haad 		dm_free(device_name);
   2896      1.1  haad 		return 0;
   2897      1.1  haad 	}
   2898      1.1  haad 	_switches[TABLE_ARG]++;
   2899      1.1  haad 
   2900      1.1  haad 	(*argv)[0] = (char *) "create";
   2901      1.1  haad 	(*argv)[1] = device_name ;
   2902      1.1  haad 
   2903      1.1  haad 	return 1;
   2904      1.1  haad }
   2905      1.1  haad 
   2906      1.1  haad static int _process_switches(int *argc, char ***argv, const char *dev_dir)
   2907      1.1  haad {
   2908      1.1  haad 	char *base, *namebase, *s;
   2909      1.1  haad 	static int ind;
   2910      1.1  haad 	int c, r;
   2911      1.1  haad 
   2912      1.1  haad #ifdef HAVE_GETOPTLONG
   2913      1.1  haad 	static struct option long_options[] = {
   2914      1.1  haad 		{"readonly", 0, &ind, READ_ONLY},
   2915      1.1  haad 		{"columns", 0, &ind, COLS_ARG},
   2916      1.1  haad 		{"exec", 1, &ind, EXEC_ARG},
   2917      1.1  haad 		{"force", 0, &ind, FORCE_ARG},
   2918      1.1  haad 		{"gid", 1, &ind, GID_ARG},
   2919  1.1.1.2  haad 		{"inactive", 0, &ind, INACTIVE_ARG},
   2920      1.1  haad 		{"major", 1, &ind, MAJOR_ARG},
   2921      1.1  haad 		{"minor", 1, &ind, MINOR_ARG},
   2922      1.1  haad 		{"mode", 1, &ind, MODE_ARG},
   2923      1.1  haad 		{"nameprefixes", 0, &ind, NAMEPREFIXES_ARG},
   2924      1.1  haad 		{"noflush", 0, &ind, NOFLUSH_ARG},
   2925      1.1  haad 		{"noheadings", 0, &ind, NOHEADINGS_ARG},
   2926      1.1  haad 		{"nolockfs", 0, &ind, NOLOCKFS_ARG},
   2927      1.1  haad 		{"noopencount", 0, &ind, NOOPENCOUNT_ARG},
   2928      1.1  haad 		{"notable", 0, &ind, NOTABLE_ARG},
   2929  1.1.1.2  haad 		{"noudevsync", 0, &ind, NOUDEVSYNC_ARG},
   2930      1.1  haad 		{"options", 1, &ind, OPTIONS_ARG},
   2931      1.1  haad 		{"readahead", 1, &ind, READAHEAD_ARG},
   2932      1.1  haad 		{"rows", 0, &ind, ROWS_ARG},
   2933      1.1  haad 		{"separator", 1, &ind, SEPARATOR_ARG},
   2934      1.1  haad 		{"showkeys", 0, &ind, SHOWKEYS_ARG},
   2935      1.1  haad 		{"sort", 1, &ind, SORT_ARG},
   2936      1.1  haad 		{"table", 1, &ind, TABLE_ARG},
   2937      1.1  haad 		{"target", 1, &ind, TARGET_ARG},
   2938      1.1  haad 		{"tree", 0, &ind, TREE_ARG},
   2939      1.1  haad 		{"uid", 1, &ind, UID_ARG},
   2940      1.1  haad 		{"uuid", 1, &ind, UUID_ARG},
   2941      1.1  haad 		{"unbuffered", 0, &ind, UNBUFFERED_ARG},
   2942      1.1  haad 		{"unquoted", 0, &ind, UNQUOTED_ARG},
   2943      1.1  haad 		{"verbose", 1, &ind, VERBOSE_ARG},
   2944      1.1  haad 		{"version", 0, &ind, VERSION_ARG},
   2945  1.1.1.2  haad 		{"yes", 0, &ind, YES_ARG},
   2946      1.1  haad 		{0, 0, 0, 0}
   2947      1.1  haad 	};
   2948      1.1  haad #else
   2949      1.1  haad 	struct option long_options;
   2950      1.1  haad #endif
   2951      1.1  haad 
   2952      1.1  haad 	/*
   2953      1.1  haad 	 * Zero all the index counts.
   2954      1.1  haad 	 */
   2955      1.1  haad 	memset(&_switches, 0, sizeof(_switches));
   2956      1.1  haad 	memset(&_int_args, 0, sizeof(_int_args));
   2957      1.1  haad 	_read_ahead_flags = 0;
   2958      1.1  haad 
   2959      1.1  haad 	namebase = strdup((*argv)[0]);
   2960      1.1  haad 	base = basename(namebase);
   2961      1.1  haad 
   2962      1.1  haad 	if (!strcmp(base, "devmap_name")) {
   2963      1.1  haad 		free(namebase);
   2964      1.1  haad 		_switches[COLS_ARG]++;
   2965      1.1  haad 		_switches[NOHEADINGS_ARG]++;
   2966      1.1  haad 		_switches[OPTIONS_ARG]++;
   2967      1.1  haad 		_switches[MAJOR_ARG]++;
   2968      1.1  haad 		_switches[MINOR_ARG]++;
   2969      1.1  haad 		_string_args[OPTIONS_ARG] = (char *) "name";
   2970      1.1  haad 
   2971      1.1  haad 		if (*argc == 3) {
   2972      1.1  haad 			_int_args[MAJOR_ARG] = atoi((*argv)[1]);
   2973      1.1  haad 			_int_args[MINOR_ARG] = atoi((*argv)[2]);
   2974      1.1  haad 			*argc -= 2;
   2975      1.1  haad 			*argv += 2;
   2976      1.1  haad 		} else if ((*argc == 2) &&
   2977      1.1  haad 			   (2 == sscanf((*argv)[1], "%i:%i",
   2978      1.1  haad 					&_int_args[MAJOR_ARG],
   2979      1.1  haad 					&_int_args[MINOR_ARG]))) {
   2980      1.1  haad 			*argc -= 1;
   2981      1.1  haad 			*argv += 1;
   2982      1.1  haad 		} else {
   2983      1.1  haad 			fprintf(stderr, "Usage: devmap_name <major> <minor>\n");
   2984      1.1  haad 			return 0;
   2985      1.1  haad 		}
   2986      1.1  haad 
   2987      1.1  haad 		(*argv)[0] = (char *) "info";
   2988      1.1  haad 		return 1;
   2989      1.1  haad 	}
   2990      1.1  haad 
   2991      1.1  haad 	if (!strcmp(base, "losetup") || !strcmp(base, "dmlosetup")){
   2992      1.1  haad 		r = _process_losetup_switches(base, argc, argv, dev_dir);
   2993      1.1  haad 		free(namebase);
   2994      1.1  haad 		return r;
   2995      1.1  haad 	}
   2996      1.1  haad 
   2997      1.1  haad 	free(namebase);
   2998      1.1  haad 
   2999      1.1  haad 	optarg = 0;
   3000      1.1  haad 	optind = OPTIND_INIT;
   3001  1.1.1.2  haad 	while ((ind = -1, c = GETOPTLONG_FN(*argc, *argv, "cCfG:j:m:M:no:O:ru:U:vy",
   3002      1.1  haad 					    long_options, NULL)) != -1) {
   3003      1.1  haad 		if (c == ':' || c == '?')
   3004      1.1  haad 			return 0;
   3005      1.1  haad 		if (c == 'c' || c == 'C' || ind == COLS_ARG)
   3006      1.1  haad 			_switches[COLS_ARG]++;
   3007      1.1  haad 		if (c == 'f' || ind == FORCE_ARG)
   3008      1.1  haad 			_switches[FORCE_ARG]++;
   3009      1.1  haad 		if (c == 'r' || ind == READ_ONLY)
   3010      1.1  haad 			_switches[READ_ONLY]++;
   3011      1.1  haad 		if (c == 'j' || ind == MAJOR_ARG) {
   3012      1.1  haad 			_switches[MAJOR_ARG]++;
   3013      1.1  haad 			_int_args[MAJOR_ARG] = atoi(optarg);
   3014      1.1  haad 		}
   3015      1.1  haad 		if (c == 'm' || ind == MINOR_ARG) {
   3016      1.1  haad 			_switches[MINOR_ARG]++;
   3017      1.1  haad 			_int_args[MINOR_ARG] = atoi(optarg);
   3018      1.1  haad 		}
   3019      1.1  haad 		if (c == 'n' || ind == NOTABLE_ARG)
   3020      1.1  haad 			_switches[NOTABLE_ARG]++;
   3021      1.1  haad 		if (c == 'o' || ind == OPTIONS_ARG) {
   3022      1.1  haad 			_switches[OPTIONS_ARG]++;
   3023      1.1  haad 			_string_args[OPTIONS_ARG] = optarg;
   3024      1.1  haad 		}
   3025      1.1  haad 		if (ind == SEPARATOR_ARG) {
   3026      1.1  haad 			_switches[SEPARATOR_ARG]++;
   3027      1.1  haad 			_string_args[SEPARATOR_ARG] = optarg;
   3028      1.1  haad 		}
   3029      1.1  haad 		if (c == 'O' || ind == SORT_ARG) {
   3030      1.1  haad 			_switches[SORT_ARG]++;
   3031      1.1  haad 			_string_args[SORT_ARG] = optarg;
   3032      1.1  haad 		}
   3033      1.1  haad 		if (c == 'v' || ind == VERBOSE_ARG)
   3034      1.1  haad 			_switches[VERBOSE_ARG]++;
   3035      1.1  haad 		if (c == 'u' || ind == UUID_ARG) {
   3036      1.1  haad 			_switches[UUID_ARG]++;
   3037      1.1  haad 			_uuid = optarg;
   3038      1.1  haad 		}
   3039  1.1.1.2  haad 		if (c == 'y' || ind == YES_ARG)
   3040  1.1.1.2  haad 			_switches[YES_ARG]++;
   3041  1.1.1.2  haad 		if (ind == NOUDEVSYNC_ARG)
   3042  1.1.1.2  haad 			_switches[NOUDEVSYNC_ARG]++;
   3043      1.1  haad 		if (c == 'G' || ind == GID_ARG) {
   3044      1.1  haad 			_switches[GID_ARG]++;
   3045      1.1  haad 			_int_args[GID_ARG] = atoi(optarg);
   3046      1.1  haad 		}
   3047      1.1  haad 		if (c == 'U' || ind == UID_ARG) {
   3048      1.1  haad 			_switches[UID_ARG]++;
   3049      1.1  haad 			_int_args[UID_ARG] = atoi(optarg);
   3050      1.1  haad 		}
   3051      1.1  haad 		if (c == 'M' || ind == MODE_ARG) {
   3052      1.1  haad 			_switches[MODE_ARG]++;
   3053      1.1  haad 			/* FIXME Accept modes as per chmod */
   3054      1.1  haad 			_int_args[MODE_ARG] = (int) strtol(optarg, NULL, 8);
   3055      1.1  haad 		}
   3056      1.1  haad 		if ((ind == EXEC_ARG)) {
   3057      1.1  haad 			_switches[EXEC_ARG]++;
   3058      1.1  haad 			_command = optarg;
   3059      1.1  haad 		}
   3060      1.1  haad 		if ((ind == TARGET_ARG)) {
   3061      1.1  haad 			_switches[TARGET_ARG]++;
   3062      1.1  haad 			_target = optarg;
   3063      1.1  haad 		}
   3064  1.1.1.2  haad 		if ((ind == INACTIVE_ARG))
   3065  1.1.1.2  haad 			_switches[INACTIVE_ARG]++;
   3066      1.1  haad 		if ((ind == NAMEPREFIXES_ARG))
   3067      1.1  haad 			_switches[NAMEPREFIXES_ARG]++;
   3068      1.1  haad 		if ((ind == NOFLUSH_ARG))
   3069      1.1  haad 			_switches[NOFLUSH_ARG]++;
   3070      1.1  haad 		if ((ind == NOHEADINGS_ARG))
   3071      1.1  haad 			_switches[NOHEADINGS_ARG]++;
   3072      1.1  haad 		if ((ind == NOLOCKFS_ARG))
   3073      1.1  haad 			_switches[NOLOCKFS_ARG]++;
   3074      1.1  haad 		if ((ind == NOOPENCOUNT_ARG))
   3075      1.1  haad 			_switches[NOOPENCOUNT_ARG]++;
   3076      1.1  haad 		if ((ind == READAHEAD_ARG)) {
   3077      1.1  haad 			_switches[READAHEAD_ARG]++;
   3078      1.1  haad 			if (!strcasecmp(optarg, "auto"))
   3079      1.1  haad 				_int_args[READAHEAD_ARG] = DM_READ_AHEAD_AUTO;
   3080      1.1  haad 			else if (!strcasecmp(optarg, "none"))
   3081      1.1  haad                 		_int_args[READAHEAD_ARG] = DM_READ_AHEAD_NONE;
   3082      1.1  haad 			else {
   3083      1.1  haad 				for (s = optarg; isspace(*s); s++)
   3084      1.1  haad 					;
   3085      1.1  haad 				if (*s == '+')
   3086      1.1  haad 					_read_ahead_flags = DM_READ_AHEAD_MINIMUM_FLAG;
   3087      1.1  haad 				_int_args[READAHEAD_ARG] = atoi(optarg);
   3088      1.1  haad 				if (_int_args[READAHEAD_ARG] < -1) {
   3089      1.1  haad 					log_error("Negative read ahead value "
   3090      1.1  haad 						  "(%d) is not understood.",
   3091      1.1  haad 						  _int_args[READAHEAD_ARG]);
   3092      1.1  haad 					return 0;
   3093      1.1  haad 				}
   3094      1.1  haad 			}
   3095      1.1  haad 		}
   3096      1.1  haad 		if ((ind == ROWS_ARG))
   3097      1.1  haad 			_switches[ROWS_ARG]++;
   3098      1.1  haad 		if ((ind == SHOWKEYS_ARG))
   3099      1.1  haad 			_switches[SHOWKEYS_ARG]++;
   3100      1.1  haad 		if ((ind == TABLE_ARG)) {
   3101      1.1  haad 			_switches[TABLE_ARG]++;
   3102      1.1  haad 			_table = optarg;
   3103      1.1  haad 		}
   3104      1.1  haad 		if ((ind == TREE_ARG))
   3105      1.1  haad 			_switches[TREE_ARG]++;
   3106      1.1  haad 		if ((ind == UNQUOTED_ARG))
   3107      1.1  haad 			_switches[UNQUOTED_ARG]++;
   3108      1.1  haad 		if ((ind == VERSION_ARG))
   3109      1.1  haad 			_switches[VERSION_ARG]++;
   3110      1.1  haad 	}
   3111      1.1  haad 
   3112      1.1  haad 	if (_switches[VERBOSE_ARG] > 1)
   3113      1.1  haad 		dm_log_init_verbose(_switches[VERBOSE_ARG] - 1);
   3114      1.1  haad 
   3115      1.1  haad 	if ((_switches[MAJOR_ARG] && !_switches[MINOR_ARG]) ||
   3116      1.1  haad 	    (!_switches[MAJOR_ARG] && _switches[MINOR_ARG])) {
   3117      1.1  haad 		fprintf(stderr, "Please specify both major number and "
   3118      1.1  haad 				"minor number.\n");
   3119      1.1  haad 		return 0;
   3120      1.1  haad 	}
   3121      1.1  haad 
   3122      1.1  haad 	if (_switches[TREE_ARG] && !_process_tree_options(_string_args[OPTIONS_ARG]))
   3123      1.1  haad 		return 0;
   3124      1.1  haad 
   3125      1.1  haad 	if (_switches[TABLE_ARG] && _switches[NOTABLE_ARG]) {
   3126      1.1  haad 		fprintf(stderr, "--table and --notable are incompatible.\n");
   3127      1.1  haad 		return 0;
   3128      1.1  haad 	}
   3129      1.1  haad 
   3130      1.1  haad 	*argv += optind;
   3131      1.1  haad 	*argc -= optind;
   3132      1.1  haad 	return 1;
   3133      1.1  haad }
   3134      1.1  haad 
   3135      1.1  haad int main(int argc, char **argv)
   3136      1.1  haad {
   3137      1.1  haad 	struct command *c;
   3138      1.1  haad 	int r = 1;
   3139      1.1  haad 	const char *dev_dir;
   3140      1.1  haad 
   3141      1.1  haad 	(void) setlocale(LC_ALL, "");
   3142      1.1  haad 
   3143      1.1  haad 	dev_dir = getenv ("DM_DEV_DIR");
   3144      1.1  haad 	if (dev_dir && *dev_dir) {
   3145      1.1  haad 		if (!dm_set_dev_dir(dev_dir)) {
   3146      1.1  haad 			fprintf(stderr, "Invalid DM_DEV_DIR environment variable value.\n");
   3147      1.1  haad 			goto out;
   3148      1.1  haad 		}
   3149      1.1  haad 	} else
   3150      1.1  haad 		dev_dir = DEFAULT_DM_DEV_DIR;
   3151      1.1  haad 
   3152      1.1  haad 	if (!_process_switches(&argc, &argv, dev_dir)) {
   3153      1.1  haad 		fprintf(stderr, "Couldn't process command line.\n");
   3154      1.1  haad 		goto out;
   3155      1.1  haad 	}
   3156      1.1  haad 
   3157      1.1  haad 	if (_switches[VERSION_ARG]) {
   3158      1.1  haad 		c = _find_command("version");
   3159      1.1  haad 		goto doit;
   3160      1.1  haad 	}
   3161      1.1  haad 
   3162      1.1  haad 	if (argc == 0) {
   3163      1.1  haad 		_usage(stderr);
   3164      1.1  haad 		goto out;
   3165      1.1  haad 	}
   3166      1.1  haad 
   3167      1.1  haad 	if (!(c = _find_command(argv[0]))) {
   3168      1.1  haad 		fprintf(stderr, "Unknown command\n");
   3169      1.1  haad 		_usage(stderr);
   3170      1.1  haad 		goto out;
   3171      1.1  haad 	}
   3172      1.1  haad 
   3173      1.1  haad 	if (argc < c->min_args + 1 ||
   3174      1.1  haad 	    (c->max_args >= 0 && argc > c->max_args + 1)) {
   3175      1.1  haad 		fprintf(stderr, "Incorrect number of arguments\n");
   3176      1.1  haad 		_usage(stderr);
   3177      1.1  haad 		goto out;
   3178      1.1  haad 	}
   3179      1.1  haad 
   3180  1.1.1.2  haad 	if (!_switches[COLS_ARG] && !strcmp(c->name, "splitname"))
   3181  1.1.1.2  haad 		_switches[COLS_ARG]++;
   3182  1.1.1.2  haad 
   3183      1.1  haad 	if (_switches[COLS_ARG] && !_report_init(c))
   3184      1.1  haad 		goto out;
   3185      1.1  haad 
   3186  1.1.1.2  haad 	if (_switches[NOUDEVSYNC_ARG])
   3187  1.1.1.2  haad 		dm_udev_set_sync_support(0);
   3188  1.1.1.2  haad 
   3189      1.1  haad       doit:
   3190      1.1  haad 	if (!c->fn(argc, argv, NULL)) {
   3191      1.1  haad 		fprintf(stderr, "Command failed\n");
   3192      1.1  haad 		goto out;
   3193      1.1  haad 	}
   3194      1.1  haad 
   3195      1.1  haad 	r = 0;
   3196      1.1  haad 
   3197      1.1  haad out:
   3198      1.1  haad 	if (_report) {
   3199      1.1  haad 		dm_report_output(_report);
   3200      1.1  haad 		dm_report_free(_report);
   3201      1.1  haad 	}
   3202      1.1  haad 
   3203      1.1  haad 	if (_dtree)
   3204      1.1  haad 		dm_tree_free(_dtree);
   3205      1.1  haad 
   3206      1.1  haad 	return r;
   3207      1.1  haad }
   3208