Sync usage with man page.
[netbsd-mini2440.git] / external / gpl2 / lvm2 / dist / tools / lvmcmdline.c
blobab225ca792e235851bb9ca0068f1a1aee01523ce
1 /* $NetBSD$ */
3 /*
4 * Copyright (C) 2001-2004 Sistina Software, Inc. All rights reserved.
5 * Copyright (C) 2004-2009 Red Hat, Inc. All rights reserved.
7 * This file is part of LVM2.
9 * This copyrighted material is made available to anyone wishing to use,
10 * modify, copy, or redistribute it subject to the terms and conditions
11 * of the GNU Lesser General Public License v.2.1.
13 * You should have received a copy of the GNU Lesser General Public License
14 * along with this program; if not, write to the Free Software Foundation,
15 * Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
18 #include "tools.h"
19 #include "lvm2cmdline.h"
20 #include "label.h"
21 #include "lvm-version.h"
23 #include "stub.h"
24 #include "lvm2cmd.h"
25 #include "last-path-component.h"
27 #include <signal.h>
28 #include <syslog.h>
29 #include <libgen.h>
30 #include <sys/stat.h>
31 #include <time.h>
32 #include <sys/resource.h>
34 #ifdef HAVE_GETOPTLONG
35 # include <getopt.h>
36 # define GETOPTLONG_FN(a, b, c, d, e) getopt_long((a), (b), (c), (d), (e))
37 # define OPTIND_INIT 0
38 #else
39 struct option {
41 extern int optind;
42 extern char *optarg;
43 # define GETOPTLONG_FN(a, b, c, d, e) getopt((a), (b), (c))
44 # define OPTIND_INIT 1
45 #endif
48 * Table of valid switches
50 static struct arg _the_args[ARG_COUNT + 1] = {
51 #define arg(a, b, c, d, e) {b, "", "--" c, d, e, 0, NULL, 0, 0, INT64_C(0), UINT64_C(0), SIGN_NONE, PERCENT_NONE, NULL},
52 #include "args.h"
53 #undef arg
56 static struct cmdline_context _cmdline;
58 /* Command line args */
59 /* FIXME: Move static _the_args into cmd? */
60 unsigned arg_count(const struct cmd_context *cmd __attribute((unused)), int a)
62 return _the_args[a].count;
65 unsigned arg_is_set(const struct cmd_context *cmd, int a)
67 return arg_count(cmd, a) ? 1 : 0;
70 const char *arg_value(struct cmd_context *cmd __attribute((unused)), int a)
72 return _the_args[a].value;
75 const char *arg_str_value(struct cmd_context *cmd, int a, const char *def)
77 return arg_count(cmd, a) ? _the_args[a].value : def;
80 int32_t arg_int_value(struct cmd_context *cmd, int a, const int32_t def)
82 return arg_count(cmd, a) ? _the_args[a].i_value : def;
85 uint32_t arg_uint_value(struct cmd_context *cmd, int a, const uint32_t def)
87 return arg_count(cmd, a) ? _the_args[a].ui_value : def;
90 int64_t arg_int64_value(struct cmd_context *cmd, int a, const int64_t def)
92 return arg_count(cmd, a) ? _the_args[a].i64_value : def;
95 uint64_t arg_uint64_value(struct cmd_context *cmd, int a, const uint64_t def)
97 return arg_count(cmd, a) ? _the_args[a].ui64_value : def;
100 const void *arg_ptr_value(struct cmd_context *cmd, int a, const void *def)
102 return arg_count(cmd, a) ? _the_args[a].ptr : def;
105 sign_t arg_sign_value(struct cmd_context *cmd, int a, const sign_t def)
107 return arg_count(cmd, a) ? _the_args[a].sign : def;
110 percent_t arg_percent_value(struct cmd_context *cmd, int a, const percent_t def)
112 return arg_count(cmd, a) ? _the_args[a].percent : def;
115 int arg_count_increment(struct cmd_context *cmd __attribute((unused)), int a)
117 return _the_args[a].count++;
120 int yes_no_arg(struct cmd_context *cmd __attribute((unused)), struct arg *a)
122 a->sign = SIGN_NONE;
123 a->percent = PERCENT_NONE;
125 if (!strcmp(a->value, "y")) {
126 a->i_value = 1;
127 a->ui_value = 1;
130 else if (!strcmp(a->value, "n")) {
131 a->i_value = 0;
132 a->ui_value = 0;
135 else
136 return 0;
138 return 1;
141 int yes_no_excl_arg(struct cmd_context *cmd __attribute((unused)),
142 struct arg *a)
144 a->sign = SIGN_NONE;
145 a->percent = PERCENT_NONE;
147 if (!strcmp(a->value, "e") || !strcmp(a->value, "ey") ||
148 !strcmp(a->value, "ye")) {
149 a->i_value = CHANGE_AE;
150 a->ui_value = CHANGE_AE;
153 else if (!strcmp(a->value, "y")) {
154 a->i_value = CHANGE_AY;
155 a->ui_value = CHANGE_AY;
158 else if (!strcmp(a->value, "n") || !strcmp(a->value, "en") ||
159 !strcmp(a->value, "ne")) {
160 a->i_value = CHANGE_AN;
161 a->ui_value = CHANGE_AN;
164 else if (!strcmp(a->value, "ln") || !strcmp(a->value, "nl")) {
165 a->i_value = CHANGE_ALN;
166 a->ui_value = CHANGE_ALN;
169 else if (!strcmp(a->value, "ly") || !strcmp(a->value, "yl")) {
170 a->i_value = CHANGE_ALY;
171 a->ui_value = CHANGE_ALY;
174 else
175 return 0;
177 return 1;
180 int metadatatype_arg(struct cmd_context *cmd, struct arg *a)
182 struct format_type *fmt;
183 char *format;
185 format = a->value;
187 dm_list_iterate_items(fmt, &cmd->formats) {
188 if (!strcasecmp(fmt->name, format) ||
189 !strcasecmp(fmt->name + 3, format) ||
190 (fmt->alias && !strcasecmp(fmt->alias, format))) {
191 a->ptr = fmt;
192 return 1;
196 return 0;
199 static int _get_int_arg(struct arg *a, char **ptr)
201 char *val;
202 long v;
204 a->percent = PERCENT_NONE;
206 val = a->value;
207 switch (*val) {
208 case '+':
209 a->sign = SIGN_PLUS;
210 val++;
211 break;
212 case '-':
213 a->sign = SIGN_MINUS;
214 val++;
215 break;
216 default:
217 a->sign = SIGN_NONE;
220 if (!isdigit(*val))
221 return 0;
223 v = strtol(val, ptr, 10);
225 if (*ptr == val)
226 return 0;
228 a->i_value = (int32_t) v;
229 a->ui_value = (uint32_t) v;
230 a->i64_value = (int64_t) v;
231 a->ui64_value = (uint64_t) v;
233 return 1;
236 /* Size stored in sectors */
237 static int _size_arg(struct cmd_context *cmd __attribute((unused)), struct arg *a, int factor)
239 char *ptr;
240 int i;
241 static const char *suffixes = "kmgtpebs";
242 char *val;
243 double v;
244 uint64_t v_tmp, adjustment;
246 a->percent = PERCENT_NONE;
248 val = a->value;
249 switch (*val) {
250 case '+':
251 a->sign = SIGN_PLUS;
252 val++;
253 break;
254 case '-':
255 a->sign = SIGN_MINUS;
256 val++;
257 break;
258 default:
259 a->sign = SIGN_NONE;
262 if (!isdigit(*val))
263 return 0;
265 v = strtod(val, &ptr);
267 if (ptr == val)
268 return 0;
270 if (*ptr) {
271 for (i = strlen(suffixes) - 1; i >= 0; i--)
272 if (suffixes[i] == tolower((int) *ptr))
273 break;
275 if (i < 0) {
276 return 0;
277 } else if (i == 7) {
278 /* sectors */
279 v = v;
280 } else if (i == 6) {
281 /* bytes */
282 v_tmp = (uint64_t) v;
283 adjustment = v_tmp % 512;
284 if (adjustment) {
285 v_tmp += (512 - adjustment);
286 log_error("Size is not a multiple of 512. "
287 "Try using %"PRIu64" or %"PRIu64".",
288 v_tmp - 512, v_tmp);
289 return 0;
291 v /= 512;
292 } else {
293 /* all other units: kmgtpe */
294 while (i-- > 0)
295 v *= 1024;
296 v *= 2;
298 } else
299 v *= factor;
301 a->i_value = (int32_t) v;
302 a->ui_value = (uint32_t) v;
303 a->i64_value = (int64_t) v;
304 a->ui64_value = (uint64_t) v;
306 return 1;
309 int size_kb_arg(struct cmd_context *cmd, struct arg *a)
311 return _size_arg(cmd, a, 2);
314 int size_mb_arg(struct cmd_context *cmd, struct arg *a)
316 return _size_arg(cmd, a, 2048);
319 int int_arg(struct cmd_context *cmd __attribute((unused)), struct arg *a)
321 char *ptr;
323 if (!_get_int_arg(a, &ptr) || (*ptr) || (a->sign == SIGN_MINUS))
324 return 0;
326 return 1;
329 int int_arg_with_sign(struct cmd_context *cmd __attribute((unused)), struct arg *a)
331 char *ptr;
333 if (!_get_int_arg(a, &ptr) || (*ptr))
334 return 0;
336 return 1;
339 int int_arg_with_sign_and_percent(struct cmd_context *cmd __attribute((unused)),
340 struct arg *a)
342 char *ptr;
344 if (!_get_int_arg(a, &ptr))
345 return 0;
347 if (!*ptr)
348 return 1;
350 if (*ptr++ != '%')
351 return 0;
353 if (!strcasecmp(ptr, "V") || !strcasecmp(ptr, "VG"))
354 a->percent = PERCENT_VG;
355 else if (!strcasecmp(ptr, "L") || !strcasecmp(ptr, "LV"))
356 a->percent = PERCENT_LV;
357 else if (!strcasecmp(ptr, "P") || !strcasecmp(ptr, "PV") ||
358 !strcasecmp(ptr, "PVS"))
359 a->percent = PERCENT_PVS;
360 else if (!strcasecmp(ptr, "F") || !strcasecmp(ptr, "FR") ||
361 !strcasecmp(ptr, "FREE"))
362 a->percent = PERCENT_FREE;
363 else
364 return 0;
366 return 1;
369 int minor_arg(struct cmd_context *cmd __attribute((unused)), struct arg *a)
371 char *ptr;
373 if (!_get_int_arg(a, &ptr) || (*ptr) || (a->sign == SIGN_MINUS))
374 return 0;
376 if (a->i_value > 255) {
377 log_error("Minor number outside range 0-255");
378 return 0;
381 return 1;
384 int major_arg(struct cmd_context *cmd __attribute((unused)), struct arg *a)
386 char *ptr;
388 if (!_get_int_arg(a, &ptr) || (*ptr) || (a->sign == SIGN_MINUS))
389 return 0;
391 if (a->i_value > 255) {
392 log_error("Major number outside range 0-255");
393 return 0;
396 /* FIXME Also Check against /proc/devices */
398 return 1;
401 int string_arg(struct cmd_context *cmd __attribute((unused)),
402 struct arg *a __attribute((unused)))
404 return 1;
407 int tag_arg(struct cmd_context *cmd __attribute((unused)), struct arg *a)
409 char *pos = a->value;
411 if (*pos == '@')
412 pos++;
414 if (!validate_name(pos))
415 return 0;
417 a->value = pos;
419 return 1;
422 int permission_arg(struct cmd_context *cmd __attribute((unused)), struct arg *a)
424 a->sign = SIGN_NONE;
426 if ((!strcmp(a->value, "rw")) || (!strcmp(a->value, "wr")))
427 a->ui_value = LVM_READ | LVM_WRITE;
429 else if (!strcmp(a->value, "r"))
430 a->ui_value = LVM_READ;
432 else
433 return 0;
435 return 1;
438 int alloc_arg(struct cmd_context *cmd __attribute((unused)), struct arg *a)
440 alloc_policy_t alloc;
442 a->sign = SIGN_NONE;
444 alloc = get_alloc_from_string(a->value);
445 if (alloc == ALLOC_INVALID)
446 return 0;
448 a->ui_value = (uint32_t) alloc;
450 return 1;
453 int segtype_arg(struct cmd_context *cmd, struct arg *a)
455 if (!(a->ptr = (void *) get_segtype_from_string(cmd, a->value)))
456 return 0;
458 return 1;
462 * Positive integer, zero or "auto".
464 int readahead_arg(struct cmd_context *cmd __attribute((unused)), struct arg *a)
466 if (!strcasecmp(a->value, "auto")) {
467 a->ui_value = DM_READ_AHEAD_AUTO;
468 return 1;
471 if (!strcasecmp(a->value, "none")) {
472 a->ui_value = DM_READ_AHEAD_NONE;
473 return 1;
476 if (!_size_arg(cmd, a, 1))
477 return 0;
479 if (a->sign == SIGN_MINUS)
480 return 0;
482 return 1;
485 static void __alloc(int size)
487 if (!(_cmdline.commands = dm_realloc(_cmdline.commands, sizeof(*_cmdline.commands) * size))) {
488 log_fatal("Couldn't allocate memory.");
489 exit(ECMD_FAILED);
492 _cmdline.commands_size = size;
495 static void _alloc_command(void)
497 if (!_cmdline.commands_size)
498 __alloc(32);
500 if (_cmdline.commands_size <= _cmdline.num_commands)
501 __alloc(2 * _cmdline.commands_size);
504 static void _create_new_command(const char *name, command_fn command,
505 unsigned flags,
506 const char *desc, const char *usagestr,
507 int nargs, int *args)
509 struct command *nc;
511 _alloc_command();
513 nc = _cmdline.commands + _cmdline.num_commands++;
515 nc->name = name;
516 nc->desc = desc;
517 nc->usage = usagestr;
518 nc->fn = command;
519 nc->flags = flags;
520 nc->num_args = nargs;
521 nc->valid_args = args;
524 static void _register_command(const char *name, command_fn fn, const char *desc,
525 unsigned flags, const char *usagestr, ...)
527 int nargs = 0, i;
528 int *args;
529 va_list ap;
531 /* count how many arguments we have */
532 va_start(ap, usagestr);
533 while (va_arg(ap, int) >= 0)
534 nargs++;
535 va_end(ap);
537 /* allocate space for them */
538 if (!(args = dm_malloc(sizeof(*args) * nargs))) {
539 log_fatal("Out of memory.");
540 exit(ECMD_FAILED);
543 /* fill them in */
544 va_start(ap, usagestr);
545 for (i = 0; i < nargs; i++)
546 args[i] = va_arg(ap, int);
547 va_end(ap);
549 /* enter the command in the register */
550 _create_new_command(name, fn, flags, desc, usagestr, nargs, args);
553 void lvm_register_commands(void)
555 #define xx(a, b, c, d...) _register_command(# a, a, b, c, ## d, \
556 driverloaded_ARG, \
557 debug_ARG, help_ARG, help2_ARG, \
558 version_ARG, verbose_ARG, \
559 quiet_ARG, config_ARG, -1);
560 #include "commands.h"
561 #undef xx
564 static struct command *_find_command(const char *name)
566 int i;
567 const char *base;
569 base = last_path_component(name);
571 for (i = 0; i < _cmdline.num_commands; i++) {
572 if (!strcmp(base, _cmdline.commands[i].name))
573 break;
576 if (i >= _cmdline.num_commands)
577 return 0;
579 return _cmdline.commands + i;
582 static void _short_usage(const char *name)
584 log_error("Run `%s --help' for more information.", name);
587 static int _usage(const char *name)
589 struct command *com = _find_command(name);
591 if (!com) {
592 log_print("%s: no such command.", name);
593 return 0;
596 log_print("%s: %s\n\n%s", com->name, com->desc, com->usage);
597 return 1;
601 * Sets up the short and long argument. If there
602 * is no short argument then the index of the
603 * argument in the the_args array is set as the
604 * long opt value. Yuck. Of course this means we
605 * can't have more than 'a' long arguments.
607 static void _add_getopt_arg(int arg, char **ptr, struct option **o)
609 struct arg *a = _cmdline.the_args + arg;
611 if (a->short_arg) {
612 *(*ptr)++ = a->short_arg;
614 if (a->fn)
615 *(*ptr)++ = ':';
617 #ifdef HAVE_GETOPTLONG
618 if (*(a->long_arg + 2)) {
619 (*o)->name = a->long_arg + 2;
620 (*o)->has_arg = a->fn ? 1 : 0;
621 (*o)->flag = NULL;
622 if (a->short_arg)
623 (*o)->val = a->short_arg;
624 else
625 (*o)->val = arg;
626 (*o)++;
628 #endif
631 static struct arg *_find_arg(struct command *com, int opt)
633 struct arg *a;
634 int i, arg;
636 for (i = 0; i < com->num_args; i++) {
637 arg = com->valid_args[i];
638 a = _cmdline.the_args + arg;
641 * opt should equal either the
642 * short arg, or the index into
643 * the_args.
645 if ((a->short_arg && (opt == a->short_arg)) ||
646 (!a->short_arg && (opt == arg)))
647 return a;
650 return 0;
653 static int _process_command_line(struct cmd_context *cmd, int *argc,
654 char ***argv)
656 int i, opt;
657 char str[((ARG_COUNT + 1) * 2) + 1], *ptr = str;
658 struct option opts[ARG_COUNT + 1], *o = opts;
659 struct arg *a;
661 for (i = 0; i < ARG_COUNT; i++) {
662 a = _cmdline.the_args + i;
664 /* zero the count and arg */
665 a->count = 0;
666 a->value = 0;
667 a->i_value = 0;
668 a->ui_value = 0;
669 a->i64_value = 0;
670 a->ui64_value = 0;
673 /* fill in the short and long opts */
674 for (i = 0; i < cmd->command->num_args; i++)
675 _add_getopt_arg(cmd->command->valid_args[i], &ptr, &o);
677 *ptr = '\0';
678 memset(o, 0, sizeof(*o));
680 /* initialise getopt_long & scan for command line switches */
681 optarg = 0;
682 optind = OPTIND_INIT;
683 while ((opt = GETOPTLONG_FN(*argc, *argv, str, opts, NULL)) >= 0) {
685 if (opt == '?')
686 return 0;
688 a = _find_arg(cmd->command, opt);
690 if (!a) {
691 log_fatal("Unrecognised option.");
692 return 0;
695 if (a->count && !(a->flags & ARG_REPEATABLE)) {
696 log_error("Option%s%c%s%s may not be repeated",
697 a->short_arg ? " -" : "",
698 a->short_arg ? : ' ',
699 (a->short_arg && a->long_arg) ?
700 "/" : "", a->long_arg ? : "");
701 return 0;
704 if (a->fn) {
705 if (!optarg) {
706 log_error("Option requires argument.");
707 return 0;
710 a->value = optarg;
712 if (!a->fn(cmd, a)) {
713 log_error("Invalid argument %s", optarg);
714 return 0;
718 a->count++;
721 *argc -= optind;
722 *argv += optind;
723 return 1;
726 static int _merge_synonym(struct cmd_context *cmd, int oldarg, int newarg)
728 const struct arg *old;
729 struct arg *new;
731 if (arg_count(cmd, oldarg) && arg_count(cmd, newarg)) {
732 log_error("%s and %s are synonyms. Please only supply one.",
733 _cmdline.the_args[oldarg].long_arg, _cmdline.the_args[newarg].long_arg);
734 return 0;
737 if (!arg_count(cmd, oldarg))
738 return 1;
740 old = _cmdline.the_args + oldarg;
741 new = _cmdline.the_args + newarg;
743 new->count = old->count;
744 new->value = old->value;
745 new->i_value = old->i_value;
746 new->ui_value = old->ui_value;
747 new->i64_value = old->i64_value;
748 new->ui64_value = old->ui64_value;
749 new->sign = old->sign;
751 return 1;
754 int version(struct cmd_context *cmd __attribute((unused)),
755 int argc __attribute((unused)),
756 char **argv __attribute((unused)))
758 char vsn[80];
760 log_print("LVM version: %s", LVM_VERSION);
761 if (library_version(vsn, sizeof(vsn)))
762 log_print("Library version: %s", vsn);
763 if (driver_version(vsn, sizeof(vsn)))
764 log_print("Driver version: %s", vsn);
766 return ECMD_PROCESSED;
769 static int _get_settings(struct cmd_context *cmd)
771 cmd->current_settings = cmd->default_settings;
773 if (arg_count(cmd, debug_ARG))
774 cmd->current_settings.debug = _LOG_FATAL +
775 (arg_count(cmd, debug_ARG) - 1);
777 if (arg_count(cmd, verbose_ARG))
778 cmd->current_settings.verbose = arg_count(cmd, verbose_ARG);
780 if (arg_count(cmd, quiet_ARG)) {
781 cmd->current_settings.debug = 0;
782 cmd->current_settings.verbose = 0;
785 if (arg_count(cmd, test_ARG))
786 cmd->current_settings.test = arg_count(cmd, test_ARG);
788 if (arg_count(cmd, driverloaded_ARG)) {
789 cmd->current_settings.activation =
790 arg_int_value(cmd, driverloaded_ARG,
791 cmd->default_settings.activation);
794 cmd->current_settings.archive = arg_int_value(cmd, autobackup_ARG, cmd->current_settings.archive);
795 cmd->current_settings.backup = arg_int_value(cmd, autobackup_ARG, cmd->current_settings.backup);
796 cmd->current_settings.cache_vgmetadata = cmd->command->flags & CACHE_VGMETADATA ? 1 : 0;
797 cmd->partial_activation = 0;
799 if (arg_count(cmd, partial_ARG)) {
800 cmd->partial_activation = 1;
801 log_print("Partial mode. Incomplete volume groups will "
802 "be activated read-only.");
805 if (arg_count(cmd, ignorelockingfailure_ARG))
806 init_ignorelockingfailure(1);
807 else
808 init_ignorelockingfailure(0);
810 if (arg_count(cmd, nosuffix_ARG))
811 cmd->current_settings.suffix = 0;
813 if (arg_count(cmd, units_ARG))
814 if (!(cmd->current_settings.unit_factor =
815 units_to_bytes(arg_str_value(cmd, units_ARG, ""),
816 &cmd->current_settings.unit_type))) {
817 log_error("Invalid units specification");
818 return EINVALID_CMD_LINE;
821 if (arg_count(cmd, trustcache_ARG)) {
822 if (arg_count(cmd, all_ARG)) {
823 log_error("--trustcache is incompatible with --all");
824 return EINVALID_CMD_LINE;
826 init_trust_cache(1);
827 log_warn("WARNING: Cache file of PVs will be trusted. "
828 "New devices holding PVs may get ignored.");
829 } else
830 init_trust_cache(0);
832 if (arg_count(cmd, noudevsync_ARG))
833 cmd->current_settings.udev_sync = 0;
835 /* Handle synonyms */
836 if (!_merge_synonym(cmd, resizable_ARG, resizeable_ARG) ||
837 !_merge_synonym(cmd, allocation_ARG, allocatable_ARG) ||
838 !_merge_synonym(cmd, allocation_ARG, resizeable_ARG) ||
839 !_merge_synonym(cmd, virtualoriginsize_ARG, virtualsize_ARG) ||
840 !_merge_synonym(cmd, metadatacopies_ARG, pvmetadatacopies_ARG))
841 return EINVALID_CMD_LINE;
843 /* Zero indicates success */
844 return 0;
847 static int _process_common_commands(struct cmd_context *cmd)
849 if (arg_count(cmd, help_ARG) || arg_count(cmd, help2_ARG)) {
850 _usage(cmd->command->name);
851 return ECMD_PROCESSED;
854 if (arg_count(cmd, version_ARG)) {
855 return version(cmd, 0, (char **) NULL);
858 /* Zero indicates it's OK to continue processing this command */
859 return 0;
862 static void _display_help(void)
864 int i;
866 log_error("Available lvm commands:");
867 log_error("Use 'lvm help <command>' for more information");
868 log_error(" ");
870 for (i = 0; i < _cmdline.num_commands; i++) {
871 struct command *com = _cmdline.commands + i;
873 log_error("%-16.16s%s", com->name, com->desc);
877 int help(struct cmd_context *cmd __attribute((unused)), int argc, char **argv)
879 int ret = ECMD_PROCESSED;
881 if (!argc)
882 _display_help();
883 else {
884 int i;
885 for (i = 0; i < argc; i++)
886 if (!_usage(argv[i]))
887 ret = EINVALID_CMD_LINE;
890 return ret;
893 static void _apply_settings(struct cmd_context *cmd)
895 init_debug(cmd->current_settings.debug);
896 init_verbose(cmd->current_settings.verbose + VERBOSE_BASE_LEVEL);
897 init_test(cmd->current_settings.test);
898 init_full_scan_done(0);
899 init_mirror_in_sync(0);
901 init_msg_prefix(cmd->default_settings.msg_prefix);
902 init_cmd_name(cmd->default_settings.cmd_name);
904 archive_enable(cmd, cmd->current_settings.archive);
905 backup_enable(cmd, cmd->current_settings.backup);
907 set_activation(cmd->current_settings.activation);
909 cmd->fmt = arg_ptr_value(cmd, metadatatype_ARG,
910 cmd->current_settings.fmt);
911 cmd->handles_missing_pvs = 0;
914 static const char *_copy_command_line(struct cmd_context *cmd, int argc, char **argv)
916 int i, space;
919 * Build up the complete command line, used as a
920 * description for backups.
922 if (!dm_pool_begin_object(cmd->mem, 128))
923 goto_bad;
925 for (i = 0; i < argc; i++) {
926 space = strchr(argv[i], ' ') ? 1 : 0;
928 if (space && !dm_pool_grow_object(cmd->mem, "'", 1))
929 goto_bad;
931 if (!dm_pool_grow_object(cmd->mem, argv[i], strlen(argv[i])))
932 goto_bad;
934 if (space && !dm_pool_grow_object(cmd->mem, "'", 1))
935 goto_bad;
937 if (i < (argc - 1))
938 if (!dm_pool_grow_object(cmd->mem, " ", 1))
939 goto_bad;
943 * Terminate.
945 if (!dm_pool_grow_object(cmd->mem, "\0", 1))
946 goto_bad;
948 return dm_pool_end_object(cmd->mem);
950 bad:
951 log_error("Couldn't copy command line.");
952 dm_pool_abandon_object(cmd->mem);
953 return NULL;
956 int lvm_run_command(struct cmd_context *cmd, int argc, char **argv)
958 int ret = 0;
959 int locking_type;
961 init_error_message_produced(0);
963 /* each command should start out with sigint flag cleared */
964 sigint_clear();
966 if (!(cmd->cmd_line = _copy_command_line(cmd, argc, argv))) {
967 stack;
968 return ECMD_FAILED;
971 log_debug("Parsing: %s", cmd->cmd_line);
973 if (!(cmd->command = _find_command(argv[0])))
974 return ENO_SUCH_CMD;
976 if (!_process_command_line(cmd, &argc, &argv)) {
977 log_error("Error during parsing of command line.");
978 return EINVALID_CMD_LINE;
981 set_cmd_name(cmd->command->name);
983 if (arg_count(cmd, config_ARG))
984 if ((ret = override_config_tree_from_string(cmd,
985 arg_str_value(cmd, config_ARG, "")))) {
986 ret = EINVALID_CMD_LINE;
987 goto_out;
990 if (arg_count(cmd, config_ARG) || !cmd->config_valid || config_files_changed(cmd)) {
991 /* Reinitialise various settings inc. logging, filters */
992 if (!refresh_toolcontext(cmd)) {
993 log_error("Updated config file invalid. Aborting.");
994 return ECMD_FAILED;
998 if ((ret = _get_settings(cmd)))
999 goto_out;
1000 _apply_settings(cmd);
1002 log_debug("Processing: %s", cmd->cmd_line);
1004 #ifdef O_DIRECT_SUPPORT
1005 log_debug("O_DIRECT will be used");
1006 #endif
1008 if ((ret = _process_common_commands(cmd)))
1009 goto_out;
1011 if (arg_count(cmd, nolocking_ARG))
1012 locking_type = 0;
1013 else
1014 locking_type = -1;
1016 if (!init_locking(locking_type, cmd)) {
1017 log_error("Locking type %d initialisation failed.",
1018 locking_type);
1019 ret = ECMD_FAILED;
1020 goto out;
1023 ret = cmd->command->fn(cmd, argc, argv);
1025 fin_locking();
1027 out:
1028 if (test_mode()) {
1029 log_verbose("Test mode: Wiping internal cache");
1030 lvmcache_destroy(cmd, 1);
1033 if (cmd->cft_override) {
1034 destroy_config_tree(cmd->cft_override);
1035 cmd->cft_override = NULL;
1036 /* Move this? */
1037 if (!refresh_toolcontext(cmd))
1038 stack;
1041 /* FIXME Move this? */
1042 cmd->current_settings = cmd->default_settings;
1043 _apply_settings(cmd);
1045 if (ret == EINVALID_CMD_LINE && !_cmdline.interactive)
1046 _short_usage(cmd->command->name);
1048 log_debug("Completed: %s", cmd->cmd_line);
1051 * free off any memory the command used.
1053 dm_pool_empty(cmd->mem);
1055 reset_lvm_errno(1);
1057 return ret;
1060 int lvm_split(char *str, int *argc, char **argv, int max)
1062 char *b = str, *e;
1063 *argc = 0;
1065 while (*b) {
1066 while (*b && isspace(*b))
1067 b++;
1069 if ((!*b) || (*b == '#'))
1070 break;
1072 e = b;
1073 while (*e && !isspace(*e))
1074 e++;
1076 argv[(*argc)++] = b;
1077 if (!*e)
1078 break;
1079 *e++ = '\0';
1080 b = e;
1081 if (*argc == max)
1082 break;
1085 return *argc;
1088 static const char *_get_cmdline(pid_t pid)
1090 static char _proc_cmdline[32];
1091 char buf[256];
1092 int fd;
1094 snprintf(buf, sizeof(buf), DEFAULT_PROC_DIR "/%u/cmdline", pid);
1095 if ((fd = open(buf, O_RDONLY)) > 0) {
1096 read(fd, _proc_cmdline, sizeof(_proc_cmdline) - 1);
1097 _proc_cmdline[sizeof(_proc_cmdline) - 1] = '\0';
1098 close(fd);
1099 } else
1100 _proc_cmdline[0] = '\0';
1102 return _proc_cmdline;
1105 static const char *_get_filename(int fd)
1107 static char filename[PATH_MAX];
1108 char buf[32]; /* Assumes short DEFAULT_PROC_DIR */
1109 int size;
1111 snprintf(buf, sizeof(buf), DEFAULT_PROC_DIR "/self/fd/%u", fd);
1113 if ((size = readlink(buf, filename, sizeof(filename) - 1)) == -1)
1114 filename[0] = '\0';
1115 else
1116 filename[size] = '\0';
1118 return filename;
1121 static void _close_descriptor(int fd, unsigned suppress_warnings,
1122 const char *command, pid_t ppid,
1123 const char *parent_cmdline)
1125 int r;
1126 const char *filename;
1128 /* Ignore bad file descriptors */
1129 if (fcntl(fd, F_GETFD) == -1 && errno == EBADF)
1130 return;
1132 if (!suppress_warnings)
1133 filename = _get_filename(fd);
1135 r = close(fd);
1136 if (suppress_warnings)
1137 return;
1139 if (!r)
1140 fprintf(stderr, "File descriptor %d (%s) leaked on "
1141 "%s invocation.", fd, filename, command);
1142 else if (errno == EBADF)
1143 return;
1144 else
1145 fprintf(stderr, "Close failed on stray file descriptor "
1146 "%d (%s): %s", fd, filename, strerror(errno));
1148 fprintf(stderr, " Parent PID %" PRIpid_t ": %s\n", ppid, parent_cmdline);
1151 static void _close_stray_fds(const char *command)
1153 struct rlimit rlim;
1154 int fd;
1155 unsigned suppress_warnings = 0;
1156 pid_t ppid = getppid();
1157 const char *parent_cmdline = _get_cmdline(ppid);
1159 if (getrlimit(RLIMIT_NOFILE, &rlim) < 0) {
1160 fprintf(stderr, "getrlimit(RLIMIT_NOFILE) failed: %s\n",
1161 strerror(errno));
1162 return;
1165 if (getenv("LVM_SUPPRESS_FD_WARNINGS"))
1166 suppress_warnings = 1;
1168 for (fd = 3; fd < rlim.rlim_cur; fd++)
1169 _close_descriptor(fd, suppress_warnings, command, ppid,
1170 parent_cmdline);
1173 struct cmd_context *init_lvm(void)
1175 struct cmd_context *cmd;
1177 _cmdline.the_args = &_the_args[0];
1179 if (!(cmd = create_toolcontext(0, NULL)))
1180 return_NULL;
1182 if (stored_errno()) {
1183 destroy_toolcontext(cmd);
1184 return_NULL;
1187 return cmd;
1190 static void _fin_commands(void)
1192 int i;
1194 for (i = 0; i < _cmdline.num_commands; i++)
1195 dm_free(_cmdline.commands[i].valid_args);
1197 dm_free(_cmdline.commands);
1200 void lvm_fin(struct cmd_context *cmd)
1202 _fin_commands();
1203 destroy_toolcontext(cmd);
1206 static int _run_script(struct cmd_context *cmd, int argc, char **argv)
1208 FILE *script;
1210 char buffer[CMD_LEN];
1211 int ret = 0;
1212 int magic_number = 0;
1213 char *script_file = argv[0];
1215 if ((script = fopen(script_file, "r")) == NULL)
1216 return ENO_SUCH_CMD;
1218 while (fgets(buffer, sizeof(buffer), script) != NULL) {
1219 if (!magic_number) {
1220 if (buffer[0] == '#' && buffer[1] == '!')
1221 magic_number = 1;
1222 else {
1223 ret = ENO_SUCH_CMD;
1224 break;
1227 if ((strlen(buffer) == sizeof(buffer) - 1)
1228 && (buffer[sizeof(buffer) - 1] - 2 != '\n')) {
1229 buffer[50] = '\0';
1230 log_error("Line too long (max 255) beginning: %s",
1231 buffer);
1232 ret = EINVALID_CMD_LINE;
1233 break;
1235 if (lvm_split(buffer, &argc, argv, MAX_ARGS) == MAX_ARGS) {
1236 buffer[50] = '\0';
1237 log_error("Too many arguments: %s", buffer);
1238 ret = EINVALID_CMD_LINE;
1239 break;
1241 if (!argc)
1242 continue;
1243 if (!strcmp(argv[0], "quit") || !strcmp(argv[0], "exit"))
1244 break;
1245 ret = lvm_run_command(cmd, argc, argv);
1246 if (ret != ECMD_PROCESSED) {
1247 if (!error_message_produced()) {
1248 log_debug("Internal error: Failed command did not use log_error");
1249 log_error("Command failed with status code %d.", ret);
1251 break;
1255 if (fclose(script))
1256 log_sys_error("fclose", script_file);
1258 return ret;
1262 * Determine whether we should fall back and exec the equivalent LVM1 tool
1264 static int _lvm1_fallback(struct cmd_context *cmd)
1266 char vsn[80];
1267 int dm_present;
1269 if (!find_config_tree_int(cmd, "global/fallback_to_lvm1",
1270 DEFAULT_FALLBACK_TO_LVM1) ||
1271 strncmp(cmd->kernel_vsn, "2.4.", 4))
1272 return 0;
1274 log_suppress(1);
1275 dm_present = driver_version(vsn, sizeof(vsn));
1276 log_suppress(0);
1278 if (dm_present || !lvm1_present(cmd))
1279 return 0;
1281 return 1;
1284 static void _exec_lvm1_command(char **argv)
1286 char path[PATH_MAX];
1288 if (dm_snprintf(path, sizeof(path), "%s.lvm1", argv[0]) < 0) {
1289 log_error("Failed to create LVM1 tool pathname");
1290 return;
1293 execvp(path, argv);
1294 log_sys_error("execvp", path);
1297 static void _nonroot_warning(void)
1299 if (getuid() || geteuid())
1300 log_warn("WARNING: Running as a non-root user. Functionality may be unavailable.");
1303 int lvm2_main(int argc, char **argv)
1305 const char *base;
1306 int ret, alias = 0;
1307 struct cmd_context *cmd;
1309 base = last_path_component(argv[0]);
1310 if (strcmp(base, "lvm") && strcmp(base, "lvm.static") &&
1311 strcmp(base, "initrd-lvm"))
1312 alias = 1;
1314 _close_stray_fds(base);
1316 if (is_static() && strcmp(base, "lvm.static") &&
1317 path_exists(LVM_SHARED_PATH) &&
1318 !getenv("LVM_DID_EXEC")) {
1319 setenv("LVM_DID_EXEC", base, 1);
1320 execvp(LVM_SHARED_PATH, argv);
1321 unsetenv("LVM_DID_EXEC");
1324 if (!(cmd = init_lvm()))
1325 return -1;
1327 cmd->argv = argv;
1328 lvm_register_commands();
1330 if (_lvm1_fallback(cmd)) {
1331 /* Attempt to run equivalent LVM1 tool instead */
1332 if (!alias) {
1333 argv++;
1334 argc--;
1335 alias = 0;
1337 if (!argc) {
1338 log_error("Falling back to LVM1 tools, but no "
1339 "command specified.");
1340 return ECMD_FAILED;
1342 _exec_lvm1_command(argv);
1343 return ECMD_FAILED;
1345 #ifdef READLINE_SUPPORT
1346 if (!alias && argc == 1) {
1347 _nonroot_warning();
1348 ret = lvm_shell(cmd, &_cmdline);
1349 goto out;
1351 #endif
1353 if (!alias) {
1354 if (argc < 2) {
1355 log_fatal("Please supply an LVM command.");
1356 _display_help();
1357 ret = EINVALID_CMD_LINE;
1358 goto out;
1361 argc--;
1362 argv++;
1365 _nonroot_warning();
1366 ret = lvm_run_command(cmd, argc, argv);
1367 if ((ret == ENO_SUCH_CMD) && (!alias))
1368 ret = _run_script(cmd, argc, argv);
1369 if (ret == ENO_SUCH_CMD)
1370 log_error("No such command. Try 'help'.");
1372 if ((ret != ECMD_PROCESSED) && !error_message_produced()) {
1373 log_debug("Internal error: Failed command did not use log_error");
1374 log_error("Command failed with status code %d.", ret);
1377 out:
1378 lvm_fin(cmd);
1379 if (ret == ECMD_PROCESSED)
1380 ret = 0;
1381 return ret;