/* * Author: Brian Wood (brian.j.wood@intel.com), Intel Corporation * Date: 8/07-12/07 * Description: This is a utility that can be used to register/unregister/check status * of device mapper RAID devices, see the manpage for further details. * * Copyright (C) 2003-2004 Sistina Software, Inc. All rights reserved. * Copyright (C) 2004 Red Hat, Inc. All rights reserved. * Copyright (C) 2007,2009 Intel Corp. All rights reserved. * * Streamlining by Heinz Mauelshagen <heinzm@redhat.com> * * Portions of this code (and its underlying architectural idea's) * are borrowed from LVM2 and Device Mapper. * * This copyrighted material is made available to anyone wishing to use, * modify, copy, or redistribute it subject to the terms and conditions * of the GNU General Public License v.2. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software Foundation, * Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ /* * FIXME before releasing in RHEL5 (Heinz Mauelshagen): * * * Likely after 5.3: * o integrate code with dmraid package * o support metadata updates * o remove any limitations to SATA, because dmraid must be device agnostic; * ie. the devices being registered with dmeventd have to be derived from * libdmraid metadata discovery; this essentially means a rewrite! * * FIXED: * o symbols naming consistency * o white space / indenting * o removed bogus sysfs access code in favour of "dmraid -s" for the time * being; maby share code with libdmraid-events later ? * o memory leaks * o remove code duplication * o programm exit codes * o cover error paths * o stdout/stderr in _usage() * o any (naming) limitations to Intel Matrix RAID * o replace memcpy by s[n]printf/strcpy/cat and check for memory leaks * o variable declaration consistency * o streamlined in general for better readability * o command line processing * o avoid displaying slave devices in _dm_all_monitored() * o most of the functions transferred to dmraid library */ #include <dirent.h> #include <dlfcn.h> #include <errno.h> #include <fcntl.h> #include <libgen.h> #include <stdio.h> #include <stdlib.h> #include <string.h> #include <syslog.h> #include <unistd.h> #include <dmraid/dmreg.h> #include "libdevmapper.h" #include "libdevmapper-event.h" #define ARRAY_SIZE(a) (sizeof(a) / sizeof(*a)) #define ARRAY_END(a) (a + ARRAY_SIZE(a)) #define DEFAULT_DMRAID_MIRROR_LIB "libdmraid-events.so" #define DM_DSO_REG_TOOL_VERSION "1.0.0.rc3" #define SYS_DM_LEN 256 #define MAJOR_MINOR 10 #define SYS_DM_PATH "/sys/block/dm-" #define SYS_DM_DEV "/dev" #define SYS_DM_SLAVES_DIR "/slaves" /* Command line option counters for CLI processing. */ enum option_type { OPT_a, OPT_h, OPT_m, OPT_r, OPT_u, OPT_V, OPT_SUM, OPT_MAX }; static int optc[OPT_MAX]; /* Usage for dm_dso_reg_tool. */ static const char *options = "Vh?amru"; static void _usage(const char *cmd, FILE *file) { fprintf(file, "Usage:\n" "%s -[%s]\n" "\n" " -V Show version of %s\n" "\n" " -{h/?} Show this help information\n" "\n" " -m[r|u] List all currently active device mapper devices\n" " and their current status with dmeventd\n" " for registered (-r)/unregistered (-m) devices\n" " Syntax: %s -m[u|r]\n" "\n" " -a[r|u] Same as -m, but for devices with UUID only!\n" " Syntax: %s -a[u|r]\n" "\n" " -r Register a device with dmeventd\n" " Syntax: %s -r <device name> " "<path to DSO library>\n" " Example: %s -r isw_abcdeh_Volume0" " libdmraid-events.so\n" "\n" " -u Unregister a device with dmeventd\n" " Syntax: %s -u <device name> " "[<path to DSO library>]\n" " Example: %s -u isw_abcdefgh_Volume0\n" "\n" , cmd, options, cmd, cmd, cmd, cmd, cmd, cmd, cmd); } void _test_user_id(void) { if (geteuid()) { fprintf(stderr, "This utility needs to be run as root.\n"); exit(1); } } /* Increment option counters. */ static _process_opt(int opt, const char *cmd) { struct opt_def_struct { const char opt; /* Option character. */ enum option_type type; /* The option type. */ int root; /* Flag to require root crdentials. */ }; static struct opt_def_struct optdefs[] = { { 'V', OPT_V, 0 }, /* Display tool version. */ { 'm', OPT_m, 1 }, /* List (all) devices. */ { 'a', OPT_a, 1 }, /* List (all) devices with UUID only. */ { 'r', OPT_r, 1 }, /* Register a device. */ { 'u', OPT_u, 1 }, /* Unregister a device. */ { 'h', OPT_h, 0 }, /* Help. */ { '?', OPT_h, 0 }, /* Help. */ }; struct opt_def_struct *o; for (o = optdefs; o < ARRAY_END(optdefs); o++) { if (opt == o->opt) { if (o->root) _test_user_id(); optc[o->type]++; optc[OPT_SUM]++; return; } } _usage(cmd, stderr); exit(1); } /* * Process command line options and do an initial argument check. * Covers help request and command line error. * * Return 1 for failure, 0 for success. */ static void _process_options(int argc, char **argv, const char *cmd) { int err = 0, opt; memset(optc, 0, sizeof(optc)); /* Walk command line options. */ while ((opt = getopt(argc, argv, options)) != EOF) _process_opt(opt, cmd); /* No options specified -> request help. */ if (!optc[OPT_SUM]) optc[OPT_h]++; /* Help may be the only option. */ if (optc[OPT_h]) { if (optc[OPT_SUM] > 1) err++; /* Only one of -r or -u. */ } else if (optc[OPT_r] + optc[OPT_u] > 1) err++; /* Only one of -r or -u. */ else if (optc[OPT_a] + optc[OPT_m] > 1) err++; /* With -{a|m}, no additional arguments, only {-r/-u}. */ else if (optc[OPT_a] || optc[OPT_m]) { if (argc != 2) err++; /* With -r, we need a device name and a DSO path. */ } else if (optc[OPT_r]) { if (argc != 4) err++; /* With -u, we need a device name and optionally a DSO path. */ } else if (optc[OPT_u]) { if (argc < 3 || argc > 4) err++; } if (err || optc[OPT_h]) { _usage(cmd, err ? stderr : stdout); exit(!!err); } } /* main: Process command line options + arguments. */ int main(int argc, char **argv) { int opt, ret = 0; char *cmd = basename(argv[0]); enum display_opt display_option; /* Process command line option (covers help and error). */ _process_options(argc, argv, cmd); if (optc[OPT_a] || optc[OPT_m]) { display_option = ALL; if (!optc[OPT_r] && optc[OPT_u]) display_option = UNREGISTERED; else if (optc[OPT_r] && !optc[OPT_u]) if (optc[OPT_a]) display_option = REGISTERED_WITH_UUID; else if (optc[OPT_m]) display_option = REGISTERED_NO_UUID; dm_all_monitored(display_option); } else if (optc[OPT_r]) ret = dm_register_device(argv[2], argv[3]); else if (optc[OPT_u]) ret = dm_unregister_device(argv[2], argc > 3 ? argv[3] : NULL); else if (optc[OPT_V]) printf("%s version: %s\n", cmd, DM_DSO_REG_TOOL_VERSION); return ret; } /* End main. */