1 /* $NetBSD: lvmcmdline.c,v 1.1.1.2 2009/02/18 11:17:44 haad Exp $ */ 2 3 /* 4 * Copyright (C) 2001-2004 Sistina Software, Inc. All rights reserved. 5 * Copyright (C) 2004-2007 Red Hat, Inc. All rights reserved. 6 * 7 * This file is part of LVM2. 8 * 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. 12 * 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 16 */ 17 18 #include "tools.h" 19 #include "lvm2cmdline.h" 20 #include "label.h" 21 #include "version.h" 22 23 #include "stub.h" 24 #include "lvm2cmd.h" 25 #include "last-path-component.h" 26 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> 33 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 { 40 }; 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 46 47 /* 48 * Table of valid switches 49 */ 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 54 }; 55 56 static struct cmdline_context _cmdline; 57 58 /* Command line args */ 59 /* FIXME: struct cmd_context * is unnecessary (large # files ) */ 60 unsigned arg_count(const struct cmd_context *cmd __attribute((unused)), int a) 61 { 62 return _the_args[a].count; 63 } 64 65 const char *arg_value(struct cmd_context *cmd __attribute((unused)), int a) 66 { 67 return _the_args[a].value; 68 } 69 70 const char *arg_str_value(struct cmd_context *cmd __attribute((unused)), 71 int a, const char *def) 72 { 73 return arg_count(cmd, a) ? _the_args[a].value : def; 74 } 75 76 int32_t arg_int_value(struct cmd_context *cmd __attribute((unused)), 77 int a, const int32_t def) 78 { 79 return arg_count(cmd, a) ? _the_args[a].i_value : def; 80 } 81 82 uint32_t arg_uint_value(struct cmd_context *cmd __attribute((unused)), 83 int a, const uint32_t def) 84 { 85 return arg_count(cmd, a) ? _the_args[a].ui_value : def; 86 } 87 88 int64_t arg_int64_value(struct cmd_context *cmd __attribute((unused)), 89 int a, const int64_t def) 90 { 91 return arg_count(cmd, a) ? _the_args[a].i64_value : def; 92 } 93 94 uint64_t arg_uint64_value(struct cmd_context *cmd __attribute((unused)), 95 int a, const uint64_t def) 96 { 97 return arg_count(cmd, a) ? _the_args[a].ui64_value : def; 98 } 99 100 const void *arg_ptr_value(struct cmd_context *cmd __attribute((unused)), 101 int a, const void *def) 102 { 103 return arg_count(cmd, a) ? _the_args[a].ptr : def; 104 } 105 106 sign_t arg_sign_value(struct cmd_context *cmd __attribute((unused)), 107 int a, const sign_t def) 108 { 109 return arg_count(cmd, a) ? _the_args[a].sign : def; 110 } 111 112 percent_t arg_percent_value(struct cmd_context *cmd __attribute((unused)), 113 int a, const percent_t def) 114 { 115 return arg_count(cmd, a) ? _the_args[a].percent : def; 116 } 117 118 int arg_count_increment(struct cmd_context *cmd __attribute((unused)), int a) 119 { 120 return _the_args[a].count++; 121 } 122 123 int yes_no_arg(struct cmd_context *cmd __attribute((unused)), struct arg *a) 124 { 125 a->sign = SIGN_NONE; 126 a->percent = PERCENT_NONE; 127 128 if (!strcmp(a->value, "y")) { 129 a->i_value = 1; 130 a->ui_value = 1; 131 } 132 133 else if (!strcmp(a->value, "n")) { 134 a->i_value = 0; 135 a->ui_value = 0; 136 } 137 138 else 139 return 0; 140 141 return 1; 142 } 143 144 int yes_no_excl_arg(struct cmd_context *cmd __attribute((unused)), 145 struct arg *a) 146 { 147 a->sign = SIGN_NONE; 148 a->percent = PERCENT_NONE; 149 150 if (!strcmp(a->value, "e") || !strcmp(a->value, "ey") || 151 !strcmp(a->value, "ye")) { 152 a->i_value = CHANGE_AE; 153 a->ui_value = CHANGE_AE; 154 } 155 156 else if (!strcmp(a->value, "y")) { 157 a->i_value = CHANGE_AY; 158 a->ui_value = CHANGE_AY; 159 } 160 161 else if (!strcmp(a->value, "n") || !strcmp(a->value, "en") || 162 !strcmp(a->value, "ne")) { 163 a->i_value = CHANGE_AN; 164 a->ui_value = CHANGE_AN; 165 } 166 167 else if (!strcmp(a->value, "ln") || !strcmp(a->value, "nl")) { 168 a->i_value = CHANGE_ALN; 169 a->ui_value = CHANGE_ALN; 170 } 171 172 else if (!strcmp(a->value, "ly") || !strcmp(a->value, "yl")) { 173 a->i_value = CHANGE_ALY; 174 a->ui_value = CHANGE_ALY; 175 } 176 177 else 178 return 0; 179 180 return 1; 181 } 182 183 int metadatatype_arg(struct cmd_context *cmd, struct arg *a) 184 { 185 struct format_type *fmt; 186 char *format; 187 188 format = a->value; 189 190 dm_list_iterate_items(fmt, &cmd->formats) { 191 if (!strcasecmp(fmt->name, format) || 192 !strcasecmp(fmt->name + 3, format) || 193 (fmt->alias && !strcasecmp(fmt->alias, format))) { 194 a->ptr = fmt; 195 return 1; 196 } 197 } 198 199 return 0; 200 } 201 202 static int _get_int_arg(struct arg *a, char **ptr) 203 { 204 char *val; 205 long v; 206 207 a->percent = PERCENT_NONE; 208 209 val = a->value; 210 switch (*val) { 211 case '+': 212 a->sign = SIGN_PLUS; 213 val++; 214 break; 215 case '-': 216 a->sign = SIGN_MINUS; 217 val++; 218 break; 219 default: 220 a->sign = SIGN_NONE; 221 } 222 223 if (!isdigit(*val)) 224 return 0; 225 226 v = strtol(val, ptr, 10); 227 228 if (*ptr == val) 229 return 0; 230 231 a->i_value = (int32_t) v; 232 a->ui_value = (uint32_t) v; 233 a->i64_value = (int64_t) v; 234 a->ui64_value = (uint64_t) v; 235 236 return 1; 237 } 238 239 /* Size stored in sectors */ 240 static int _size_arg(struct cmd_context *cmd __attribute((unused)), struct arg *a, int factor) 241 { 242 char *ptr; 243 int i; 244 static const char *suffixes = "kmgtpe"; 245 char *val; 246 double v; 247 248 a->percent = PERCENT_NONE; 249 250 val = a->value; 251 switch (*val) { 252 case '+': 253 a->sign = SIGN_PLUS; 254 val++; 255 break; 256 case '-': 257 a->sign = SIGN_MINUS; 258 val++; 259 break; 260 default: 261 a->sign = SIGN_NONE; 262 } 263 264 if (!isdigit(*val)) 265 return 0; 266 267 v = strtod(val, &ptr); 268 269 if (ptr == val) 270 return 0; 271 272 if (*ptr) { 273 for (i = strlen(suffixes) - 1; i >= 0; i--) 274 if (suffixes[i] == tolower((int) *ptr)) 275 break; 276 277 if (i < 0) 278 return 0; 279 280 while (i-- > 0) 281 v *= 1024; 282 283 v *= 2; 284 } else 285 v *= factor; 286 287 a->i_value = (int32_t) v; 288 a->ui_value = (uint32_t) v; 289 a->i64_value = (int64_t) v; 290 a->ui64_value = (uint64_t) v; 291 292 return 1; 293 } 294 295 int size_kb_arg(struct cmd_context *cmd, struct arg *a) 296 { 297 return _size_arg(cmd, a, 2); 298 } 299 300 int size_mb_arg(struct cmd_context *cmd, struct arg *a) 301 { 302 return _size_arg(cmd, a, 2048); 303 } 304 305 int int_arg(struct cmd_context *cmd __attribute((unused)), struct arg *a) 306 { 307 char *ptr; 308 309 if (!_get_int_arg(a, &ptr) || (*ptr) || (a->sign == SIGN_MINUS)) 310 return 0; 311 312 return 1; 313 } 314 315 int int_arg_with_sign(struct cmd_context *cmd __attribute((unused)), struct arg *a) 316 { 317 char *ptr; 318 319 if (!_get_int_arg(a, &ptr) || (*ptr)) 320 return 0; 321 322 return 1; 323 } 324 325 int int_arg_with_sign_and_percent(struct cmd_context *cmd __attribute((unused)), 326 struct arg *a) 327 { 328 char *ptr; 329 330 if (!_get_int_arg(a, &ptr)) 331 return 0; 332 333 if (!*ptr) 334 return 1; 335 336 if (*ptr++ != '%') 337 return 0; 338 339 if (!strcasecmp(ptr, "V") || !strcasecmp(ptr, "VG")) 340 a->percent = PERCENT_VG; 341 else if (!strcasecmp(ptr, "L") || !strcasecmp(ptr, "LV")) 342 a->percent = PERCENT_LV; 343 else if (!strcasecmp(ptr, "P") || !strcasecmp(ptr, "PV") || 344 !strcasecmp(ptr, "PVS")) 345 a->percent = PERCENT_PVS; 346 else if (!strcasecmp(ptr, "F") || !strcasecmp(ptr, "FR") || 347 !strcasecmp(ptr, "FREE")) 348 a->percent = PERCENT_FREE; 349 else 350 return 0; 351 352 return 1; 353 } 354 355 int minor_arg(struct cmd_context *cmd __attribute((unused)), struct arg *a) 356 { 357 char *ptr; 358 359 if (!_get_int_arg(a, &ptr) || (*ptr) || (a->sign == SIGN_MINUS)) 360 return 0; 361 362 if (a->i_value > 255) { 363 log_error("Minor number outside range 0-255"); 364 return 0; 365 } 366 367 return 1; 368 } 369 370 int major_arg(struct cmd_context *cmd __attribute((unused)), struct arg *a) 371 { 372 char *ptr; 373 374 if (!_get_int_arg(a, &ptr) || (*ptr) || (a->sign == SIGN_MINUS)) 375 return 0; 376 377 if (a->i_value > 255) { 378 log_error("Major number outside range 0-255"); 379 return 0; 380 } 381 382 /* FIXME Also Check against /proc/devices */ 383 384 return 1; 385 } 386 387 int string_arg(struct cmd_context *cmd __attribute((unused)), 388 struct arg *a __attribute((unused))) 389 { 390 return 1; 391 } 392 393 int tag_arg(struct cmd_context *cmd __attribute((unused)), struct arg *a) 394 { 395 char *pos = a->value; 396 397 if (*pos == '@') 398 pos++; 399 400 if (!validate_name(pos)) 401 return 0; 402 403 a->value = pos; 404 405 return 1; 406 } 407 408 int permission_arg(struct cmd_context *cmd __attribute((unused)), struct arg *a) 409 { 410 a->sign = SIGN_NONE; 411 412 if ((!strcmp(a->value, "rw")) || (!strcmp(a->value, "wr"))) 413 a->ui_value = LVM_READ | LVM_WRITE; 414 415 else if (!strcmp(a->value, "r")) 416 a->ui_value = LVM_READ; 417 418 else 419 return 0; 420 421 return 1; 422 } 423 424 int alloc_arg(struct cmd_context *cmd __attribute((unused)), struct arg *a) 425 { 426 alloc_policy_t alloc; 427 428 a->sign = SIGN_NONE; 429 430 alloc = get_alloc_from_string(a->value); 431 if (alloc == ALLOC_INVALID) 432 return 0; 433 434 a->ui_value = (uint32_t) alloc; 435 436 return 1; 437 } 438 439 int segtype_arg(struct cmd_context *cmd, struct arg *a) 440 { 441 if (!(a->ptr = (void *) get_segtype_from_string(cmd, a->value))) 442 return 0; 443 444 return 1; 445 } 446 447 /* 448 * Positive integer, zero or "auto". 449 */ 450 int readahead_arg(struct cmd_context *cmd __attribute((unused)), struct arg *a) 451 { 452 if (!strcasecmp(a->value, "auto")) { 453 a->ui_value = DM_READ_AHEAD_AUTO; 454 return 1; 455 } 456 457 if (!strcasecmp(a->value, "none")) { 458 a->ui_value = DM_READ_AHEAD_NONE; 459 return 1; 460 } 461 462 if (!_size_arg(cmd, a, 1)) 463 return 0; 464 465 if (a->sign == SIGN_MINUS) 466 return 0; 467 468 return 1; 469 } 470 471 static void __alloc(int size) 472 { 473 if (!(_cmdline.commands = dm_realloc(_cmdline.commands, sizeof(*_cmdline.commands) * size))) { 474 log_fatal("Couldn't allocate memory."); 475 exit(ECMD_FAILED); 476 } 477 478 _cmdline.commands_size = size; 479 } 480 481 static void _alloc_command(void) 482 { 483 if (!_cmdline.commands_size) 484 __alloc(32); 485 486 if (_cmdline.commands_size <= _cmdline.num_commands) 487 __alloc(2 * _cmdline.commands_size); 488 } 489 490 static void _create_new_command(const char *name, command_fn command, 491 unsigned flags, 492 const char *desc, const char *usagestr, 493 int nargs, int *args) 494 { 495 struct command *nc; 496 497 _alloc_command(); 498 499 nc = _cmdline.commands + _cmdline.num_commands++; 500 501 nc->name = name; 502 nc->desc = desc; 503 nc->usage = usagestr; 504 nc->fn = command; 505 nc->flags = flags; 506 nc->num_args = nargs; 507 nc->valid_args = args; 508 } 509 510 static void _register_command(const char *name, command_fn fn, const char *desc, 511 unsigned flags, const char *usagestr, ...) 512 { 513 int nargs = 0, i; 514 int *args; 515 va_list ap; 516 517 /* count how many arguments we have */ 518 va_start(ap, usagestr); 519 while (va_arg(ap, int) >= 0) 520 nargs++; 521 va_end(ap); 522 523 /* allocate space for them */ 524 if (!(args = dm_malloc(sizeof(*args) * nargs))) { 525 log_fatal("Out of memory."); 526 exit(ECMD_FAILED); 527 } 528 529 /* fill them in */ 530 va_start(ap, usagestr); 531 for (i = 0; i < nargs; i++) 532 args[i] = va_arg(ap, int); 533 va_end(ap); 534 535 /* enter the command in the register */ 536 _create_new_command(name, fn, flags, desc, usagestr, nargs, args); 537 } 538 539 void lvm_register_commands(void) 540 { 541 #define xx(a, b, c, d...) _register_command(# a, a, b, c, ## d, \ 542 driverloaded_ARG, \ 543 debug_ARG, help_ARG, help2_ARG, \ 544 version_ARG, verbose_ARG, \ 545 quiet_ARG, config_ARG, -1); 546 #include "commands.h" 547 #undef xx 548 } 549 550 static struct command *_find_command(const char *name) 551 { 552 int i; 553 const char *base; 554 555 base = last_path_component(name); 556 557 for (i = 0; i < _cmdline.num_commands; i++) { 558 if (!strcmp(base, _cmdline.commands[i].name)) 559 break; 560 } 561 562 if (i >= _cmdline.num_commands) 563 return 0; 564 565 return _cmdline.commands + i; 566 } 567 568 static void _short_usage(const char *name) 569 { 570 log_error("Run `%s --help' for more information.", name); 571 } 572 573 static int _usage(const char *name) 574 { 575 struct command *com = _find_command(name); 576 577 if (!com) { 578 log_print("%s: no such command.", name); 579 return 0; 580 } 581 582 log_print("%s: %s\n\n%s", com->name, com->desc, com->usage); 583 return 1; 584 } 585 586 /* 587 * Sets up the short and long argument. If there 588 * is no short argument then the index of the 589 * argument in the the_args array is set as the 590 * long opt value. Yuck. Of course this means we 591 * can't have more than 'a' long arguments. 592 */ 593 static void _add_getopt_arg(int arg, char **ptr, struct option **o) 594 { 595 struct arg *a = _cmdline.the_args + arg; 596 597 if (a->short_arg) { 598 *(*ptr)++ = a->short_arg; 599 600 if (a->fn) 601 *(*ptr)++ = ':'; 602 } 603 #ifdef HAVE_GETOPTLONG 604 if (*(a->long_arg + 2)) { 605 (*o)->name = a->long_arg + 2; 606 (*o)->has_arg = a->fn ? 1 : 0; 607 (*o)->flag = NULL; 608 if (a->short_arg) 609 (*o)->val = a->short_arg; 610 else 611 (*o)->val = arg; 612 (*o)++; 613 } 614 #endif 615 } 616 617 static struct arg *_find_arg(struct command *com, int opt) 618 { 619 struct arg *a; 620 int i, arg; 621 622 for (i = 0; i < com->num_args; i++) { 623 arg = com->valid_args[i]; 624 a = _cmdline.the_args + arg; 625 626 /* 627 * opt should equal either the 628 * short arg, or the index into 629 * the_args. 630 */ 631 if ((a->short_arg && (opt == a->short_arg)) || 632 (!a->short_arg && (opt == arg))) 633 return a; 634 } 635 636 return 0; 637 } 638 639 static int _process_command_line(struct cmd_context *cmd, int *argc, 640 char ***argv) 641 { 642 int i, opt; 643 char str[((ARG_COUNT + 1) * 2) + 1], *ptr = str; 644 struct option opts[ARG_COUNT + 1], *o = opts; 645 struct arg *a; 646 647 for (i = 0; i < ARG_COUNT; i++) { 648 a = _cmdline.the_args + i; 649 650 /* zero the count and arg */ 651 a->count = 0; 652 a->value = 0; 653 a->i_value = 0; 654 a->ui_value = 0; 655 a->i64_value = 0; 656 a->ui64_value = 0; 657 } 658 659 /* fill in the short and long opts */ 660 for (i = 0; i < cmd->command->num_args; i++) 661 _add_getopt_arg(cmd->command->valid_args[i], &ptr, &o); 662 663 *ptr = '\0'; 664 memset(o, 0, sizeof(*o)); 665 666 /* initialise getopt_long & scan for command line switches */ 667 optarg = 0; 668 optind = OPTIND_INIT; 669 while ((opt = GETOPTLONG_FN(*argc, *argv, str, opts, NULL)) >= 0) { 670 671 if (opt == '?') 672 return 0; 673 674 a = _find_arg(cmd->command, opt); 675 676 if (!a) { 677 log_fatal("Unrecognised option."); 678 return 0; 679 } 680 681 if (a->count && !(a->flags & ARG_REPEATABLE)) { 682 log_error("Option%s%c%s%s may not be repeated", 683 a->short_arg ? " -" : "", 684 a->short_arg ? : ' ', 685 (a->short_arg && a->long_arg) ? 686 "/" : "", a->long_arg ? : ""); 687 return 0; 688 } 689 690 if (a->fn) { 691 if (!optarg) { 692 log_error("Option requires argument."); 693 return 0; 694 } 695 696 a->value = optarg; 697 698 if (!a->fn(cmd, a)) { 699 log_error("Invalid argument %s", optarg); 700 return 0; 701 } 702 } 703 704 a->count++; 705 } 706 707 *argc -= optind; 708 *argv += optind; 709 return 1; 710 } 711 712 static int _merge_synonym(struct cmd_context *cmd, int oldarg, int newarg) 713 { 714 const struct arg *old; 715 struct arg *new; 716 717 if (arg_count(cmd, oldarg) && arg_count(cmd, newarg)) { 718 log_error("%s and %s are synonyms. Please only supply one.", 719 _cmdline.the_args[oldarg].long_arg, _cmdline.the_args[newarg].long_arg); 720 return 0; 721 } 722 723 if (!arg_count(cmd, oldarg)) 724 return 1; 725 726 old = _cmdline.the_args + oldarg; 727 new = _cmdline.the_args + newarg; 728 729 new->count = old->count; 730 new->value = old->value; 731 new->i_value = old->i_value; 732 new->ui_value = old->ui_value; 733 new->i64_value = old->i64_value; 734 new->ui64_value = old->ui64_value; 735 new->sign = old->sign; 736 737 return 1; 738 } 739 740 int version(struct cmd_context *cmd __attribute((unused)), 741 int argc __attribute((unused)), 742 char **argv __attribute((unused))) 743 { 744 char vsn[80]; 745 746 log_print("LVM version: %s", LVM_VERSION); 747 if (library_version(vsn, sizeof(vsn))) 748 log_print("Library version: %s", vsn); 749 if (driver_version(vsn, sizeof(vsn))) 750 log_print("Driver version: %s", vsn); 751 752 return ECMD_PROCESSED; 753 } 754 755 static int _get_settings(struct cmd_context *cmd) 756 { 757 cmd->current_settings = cmd->default_settings; 758 759 if (arg_count(cmd, debug_ARG)) 760 cmd->current_settings.debug = _LOG_FATAL + 761 (arg_count(cmd, debug_ARG) - 1); 762 763 if (arg_count(cmd, verbose_ARG)) 764 cmd->current_settings.verbose = arg_count(cmd, verbose_ARG); 765 766 if (arg_count(cmd, quiet_ARG)) { 767 cmd->current_settings.debug = 0; 768 cmd->current_settings.verbose = 0; 769 } 770 771 if (arg_count(cmd, test_ARG)) 772 cmd->current_settings.test = arg_count(cmd, test_ARG); 773 774 if (arg_count(cmd, driverloaded_ARG)) { 775 cmd->current_settings.activation = 776 arg_int_value(cmd, driverloaded_ARG, 777 cmd->default_settings.activation); 778 } 779 780 cmd->current_settings.archive = arg_int_value(cmd, autobackup_ARG, cmd->current_settings.archive); 781 cmd->current_settings.backup = arg_int_value(cmd, autobackup_ARG, cmd->current_settings.backup); 782 cmd->current_settings.cache_vgmetadata = cmd->command->flags & CACHE_VGMETADATA ? 1 : 0; 783 cmd->partial_activation = 0; 784 785 if (arg_count(cmd, partial_ARG)) { 786 cmd->partial_activation = 1; 787 log_print("Partial mode. Incomplete volume groups will " 788 "be activated read-only."); 789 } 790 791 if (arg_count(cmd, ignorelockingfailure_ARG)) 792 init_ignorelockingfailure(1); 793 else 794 init_ignorelockingfailure(0); 795 796 if (arg_count(cmd, nosuffix_ARG)) 797 cmd->current_settings.suffix = 0; 798 799 if (arg_count(cmd, units_ARG)) 800 if (!(cmd->current_settings.unit_factor = 801 units_to_bytes(arg_str_value(cmd, units_ARG, ""), 802 &cmd->current_settings.unit_type))) { 803 log_error("Invalid units specification"); 804 return EINVALID_CMD_LINE; 805 } 806 807 if (arg_count(cmd, trustcache_ARG)) { 808 if (arg_count(cmd, all_ARG)) { 809 log_error("--trustcache is incompatible with --all"); 810 return EINVALID_CMD_LINE; 811 } 812 init_trust_cache(1); 813 log_warn("WARNING: Cache file of PVs will be trusted. " 814 "New devices holding PVs may get ignored."); 815 } else 816 init_trust_cache(0); 817 818 /* Handle synonyms */ 819 if (!_merge_synonym(cmd, resizable_ARG, resizeable_ARG) || 820 !_merge_synonym(cmd, allocation_ARG, allocatable_ARG) || 821 !_merge_synonym(cmd, allocation_ARG, resizeable_ARG)) 822 return EINVALID_CMD_LINE; 823 824 /* Zero indicates success */ 825 return 0; 826 } 827 828 static int _process_common_commands(struct cmd_context *cmd) 829 { 830 if (arg_count(cmd, help_ARG) || arg_count(cmd, help2_ARG)) { 831 _usage(cmd->command->name); 832 return ECMD_PROCESSED; 833 } 834 835 if (arg_count(cmd, version_ARG)) { 836 return version(cmd, 0, (char **) NULL); 837 } 838 839 /* Zero indicates it's OK to continue processing this command */ 840 return 0; 841 } 842 843 static void _display_help(void) 844 { 845 int i; 846 847 log_error("Available lvm commands:"); 848 log_error("Use 'lvm help <command>' for more information"); 849 log_error(" "); 850 851 for (i = 0; i < _cmdline.num_commands; i++) { 852 struct command *com = _cmdline.commands + i; 853 854 log_error("%-16.16s%s", com->name, com->desc); 855 } 856 } 857 858 int help(struct cmd_context *cmd __attribute((unused)), int argc, char **argv) 859 { 860 int ret = ECMD_PROCESSED; 861 862 if (!argc) 863 _display_help(); 864 else { 865 int i; 866 for (i = 0; i < argc; i++) 867 if (!_usage(argv[i])) 868 ret = EINVALID_CMD_LINE; 869 } 870 871 return ret; 872 } 873 874 static int _override_settings(struct cmd_context *cmd) 875 { 876 if (!(cmd->cft_override = create_config_tree_from_string(cmd, arg_str_value(cmd, config_ARG, "")))) { 877 log_error("Failed to set overridden configuration entries."); 878 return EINVALID_CMD_LINE; 879 } 880 881 return 0; 882 } 883 884 static void _apply_settings(struct cmd_context *cmd) 885 { 886 init_debug(cmd->current_settings.debug); 887 init_verbose(cmd->current_settings.verbose + VERBOSE_BASE_LEVEL); 888 init_test(cmd->current_settings.test); 889 init_full_scan_done(0); 890 init_mirror_in_sync(0); 891 892 init_msg_prefix(cmd->default_settings.msg_prefix); 893 init_cmd_name(cmd->default_settings.cmd_name); 894 895 archive_enable(cmd, cmd->current_settings.archive); 896 backup_enable(cmd, cmd->current_settings.backup); 897 898 set_activation(cmd->current_settings.activation); 899 900 cmd->fmt = arg_ptr_value(cmd, metadatatype_ARG, 901 cmd->current_settings.fmt); 902 cmd->handles_missing_pvs = 0; 903 } 904 905 static char *_copy_command_line(struct cmd_context *cmd, int argc, char **argv) 906 { 907 int i, space; 908 909 /* 910 * Build up the complete command line, used as a 911 * description for backups. 912 */ 913 if (!dm_pool_begin_object(cmd->mem, 128)) 914 goto_bad; 915 916 for (i = 0; i < argc; i++) { 917 space = strchr(argv[i], ' ') ? 1 : 0; 918 919 if (space && !dm_pool_grow_object(cmd->mem, "'", 1)) 920 goto_bad; 921 922 if (!dm_pool_grow_object(cmd->mem, argv[i], strlen(argv[i]))) 923 goto_bad; 924 925 if (space && !dm_pool_grow_object(cmd->mem, "'", 1)) 926 goto_bad; 927 928 if (i < (argc - 1)) 929 if (!dm_pool_grow_object(cmd->mem, " ", 1)) 930 goto_bad; 931 } 932 933 /* 934 * Terminate. 935 */ 936 if (!dm_pool_grow_object(cmd->mem, "\0", 1)) 937 goto_bad; 938 939 return dm_pool_end_object(cmd->mem); 940 941 bad: 942 log_err("Couldn't copy command line."); 943 dm_pool_abandon_object(cmd->mem); 944 return NULL; 945 } 946 947 int lvm_run_command(struct cmd_context *cmd, int argc, char **argv) 948 { 949 int ret = 0; 950 int locking_type; 951 952 init_error_message_produced(0); 953 954 /* each command should start out with sigint flag cleared */ 955 sigint_clear(); 956 957 if (!(cmd->cmd_line = _copy_command_line(cmd, argc, argv))) 958 return ECMD_FAILED; 959 960 log_debug("Parsing: %s", cmd->cmd_line); 961 962 if (!(cmd->command = _find_command(argv[0]))) 963 return ENO_SUCH_CMD; 964 965 if (!_process_command_line(cmd, &argc, &argv)) { 966 log_error("Error during parsing of command line."); 967 return EINVALID_CMD_LINE; 968 } 969 970 set_cmd_name(cmd->command->name); 971 972 if (arg_count(cmd, config_ARG)) 973 if ((ret = _override_settings(cmd))) 974 goto_out; 975 976 if (arg_count(cmd, config_ARG) || !cmd->config_valid || config_files_changed(cmd)) { 977 /* Reinitialise various settings inc. logging, filters */ 978 if (!refresh_toolcontext(cmd)) { 979 log_error("Updated config file invalid. Aborting."); 980 return ECMD_FAILED; 981 } 982 } 983 984 if ((ret = _get_settings(cmd))) 985 goto_out; 986 _apply_settings(cmd); 987 988 log_debug("Processing: %s", cmd->cmd_line); 989 990 #ifdef O_DIRECT_SUPPORT 991 log_debug("O_DIRECT will be used"); 992 #endif 993 994 if ((ret = _process_common_commands(cmd))) 995 goto_out; 996 997 if (arg_count(cmd, nolocking_ARG)) 998 locking_type = 0; 999 else 1000 locking_type = find_config_tree_int(cmd, 1001 "global/locking_type", 1); 1002 1003 if (!init_locking(locking_type, cmd)) { 1004 log_error("Locking type %d initialisation failed.", 1005 locking_type); 1006 ret = ECMD_FAILED; 1007 goto out; 1008 } 1009 1010 ret = cmd->command->fn(cmd, argc, argv); 1011 1012 fin_locking(); 1013 1014 out: 1015 if (test_mode()) { 1016 log_verbose("Test mode: Wiping internal cache"); 1017 lvmcache_destroy(cmd, 1); 1018 } 1019 1020 if (cmd->cft_override) { 1021 destroy_config_tree(cmd->cft_override); 1022 cmd->cft_override = NULL; 1023 /* Move this? */ 1024 if (!refresh_toolcontext(cmd)) 1025 stack; 1026 } 1027 1028 /* FIXME Move this? */ 1029 cmd->current_settings = cmd->default_settings; 1030 _apply_settings(cmd); 1031 1032 /* 1033 * free off any memory the command used. 1034 */ 1035 dm_pool_empty(cmd->mem); 1036 1037 if (ret == EINVALID_CMD_LINE && !_cmdline.interactive) 1038 _short_usage(cmd->command->name); 1039 1040 log_debug("Completed: %s", cmd->cmd_line); 1041 1042 return ret; 1043 } 1044 1045 int lvm_split(char *str, int *argc, char **argv, int max) 1046 { 1047 char *b = str, *e; 1048 *argc = 0; 1049 1050 while (*b) { 1051 while (*b && isspace(*b)) 1052 b++; 1053 1054 if ((!*b) || (*b == '#')) 1055 break; 1056 1057 e = b; 1058 while (*e && !isspace(*e)) 1059 e++; 1060 1061 argv[(*argc)++] = b; 1062 if (!*e) 1063 break; 1064 *e++ = '\0'; 1065 b = e; 1066 if (*argc == max) 1067 break; 1068 } 1069 1070 return *argc; 1071 } 1072 1073 static const char *_get_cmdline(pid_t pid) 1074 { 1075 static char _proc_cmdline[32]; 1076 char buf[256]; 1077 int fd; 1078 1079 snprintf(buf, sizeof(buf), DEFAULT_PROC_DIR "/%u/cmdline", pid); 1080 if ((fd = open(buf, O_RDONLY)) > 0) { 1081 read(fd, _proc_cmdline, sizeof(_proc_cmdline) - 1); 1082 _proc_cmdline[sizeof(_proc_cmdline) - 1] = '\0'; 1083 close(fd); 1084 } else 1085 _proc_cmdline[0] = '\0'; 1086 1087 return _proc_cmdline; 1088 } 1089 1090 static const char *_get_filename(int fd) 1091 { 1092 static char filename[PATH_MAX]; 1093 char buf[32]; /* Assumes short DEFAULT_PROC_DIR */ 1094 int size; 1095 1096 snprintf(buf, sizeof(buf), DEFAULT_PROC_DIR "/self/fd/%u", fd); 1097 1098 if ((size = readlink(buf, filename, sizeof(filename) - 1)) == -1) 1099 filename[0] = '\0'; 1100 else 1101 filename[size] = '\0'; 1102 1103 return filename; 1104 } 1105 1106 static void _close_descriptor(int fd, unsigned suppress_warnings, 1107 const char *command, pid_t ppid, 1108 const char *parent_cmdline) 1109 { 1110 int r; 1111 const char *filename; 1112 1113 /* Ignore bad file descriptors */ 1114 if (fcntl(fd, F_GETFD) == -1 && errno == EBADF) 1115 return; 1116 1117 if (!suppress_warnings) 1118 filename = _get_filename(fd); 1119 1120 r = close(fd); 1121 if (suppress_warnings) 1122 return; 1123 1124 if (!r) 1125 fprintf(stderr, "File descriptor %d (%s) leaked on " 1126 "%s invocation.", fd, filename, command); 1127 else if (errno == EBADF) 1128 return; 1129 else 1130 fprintf(stderr, "Close failed on stray file descriptor " 1131 "%d (%s): %s", fd, filename, strerror(errno)); 1132 1133 fprintf(stderr, " Parent PID %" PRIpid_t ": %s\n", ppid, parent_cmdline); 1134 } 1135 1136 static void _close_stray_fds(const char *command) 1137 { 1138 struct rlimit rlim; 1139 int fd; 1140 unsigned suppress_warnings = 0; 1141 pid_t ppid = getppid(); 1142 const char *parent_cmdline = _get_cmdline(ppid); 1143 1144 if (getrlimit(RLIMIT_NOFILE, &rlim) < 0) { 1145 fprintf(stderr, "getrlimit(RLIMIT_NOFILE) failed: %s\n", 1146 strerror(errno)); 1147 return; 1148 } 1149 1150 if (getenv("LVM_SUPPRESS_FD_WARNINGS")) 1151 suppress_warnings = 1; 1152 1153 for (fd = 3; fd < rlim.rlim_cur; fd++) 1154 _close_descriptor(fd, suppress_warnings, command, ppid, 1155 parent_cmdline); 1156 } 1157 1158 struct cmd_context *init_lvm(void) 1159 { 1160 struct cmd_context *cmd; 1161 1162 _cmdline.the_args = &_the_args[0]; 1163 1164 if (!(cmd = create_toolcontext(0))) 1165 return_NULL; 1166 1167 return cmd; 1168 } 1169 1170 static void _fin_commands(void) 1171 { 1172 int i; 1173 1174 for (i = 0; i < _cmdline.num_commands; i++) 1175 dm_free(_cmdline.commands[i].valid_args); 1176 1177 dm_free(_cmdline.commands); 1178 } 1179 1180 void lvm_fin(struct cmd_context *cmd) 1181 { 1182 _fin_commands(); 1183 destroy_toolcontext(cmd); 1184 } 1185 1186 static int _run_script(struct cmd_context *cmd, int argc, char **argv) 1187 { 1188 FILE *script; 1189 1190 char buffer[CMD_LEN]; 1191 int ret = 0; 1192 int magic_number = 0; 1193 char *script_file = argv[0]; 1194 1195 if ((script = fopen(script_file, "r")) == NULL) 1196 return ENO_SUCH_CMD; 1197 1198 while (fgets(buffer, sizeof(buffer), script) != NULL) { 1199 if (!magic_number) { 1200 if (buffer[0] == '#' && buffer[1] == '!') 1201 magic_number = 1; 1202 else { 1203 ret = ENO_SUCH_CMD; 1204 break; 1205 } 1206 } 1207 if ((strlen(buffer) == sizeof(buffer) - 1) 1208 && (buffer[sizeof(buffer) - 1] - 2 != '\n')) { 1209 buffer[50] = '\0'; 1210 log_error("Line too long (max 255) beginning: %s", 1211 buffer); 1212 ret = EINVALID_CMD_LINE; 1213 break; 1214 } 1215 if (lvm_split(buffer, &argc, argv, MAX_ARGS) == MAX_ARGS) { 1216 buffer[50] = '\0'; 1217 log_error("Too many arguments: %s", buffer); 1218 ret = EINVALID_CMD_LINE; 1219 break; 1220 } 1221 if (!argc) 1222 continue; 1223 if (!strcmp(argv[0], "quit") || !strcmp(argv[0], "exit")) 1224 break; 1225 ret = lvm_run_command(cmd, argc, argv); 1226 if (ret != ECMD_PROCESSED) { 1227 if (!error_message_produced()) { 1228 log_debug("Internal error: Failed command did not use log_error"); 1229 log_error("Command failed with status code %d.", ret); 1230 } 1231 break; 1232 } 1233 } 1234 1235 if (fclose(script)) 1236 log_sys_error("fclose", script_file); 1237 1238 return ret; 1239 } 1240 1241 /* 1242 * Determine whether we should fall back and exec the equivalent LVM1 tool 1243 */ 1244 static int _lvm1_fallback(struct cmd_context *cmd) 1245 { 1246 char vsn[80]; 1247 int dm_present; 1248 1249 if (!find_config_tree_int(cmd, "global/fallback_to_lvm1", 1250 DEFAULT_FALLBACK_TO_LVM1) || 1251 strncmp(cmd->kernel_vsn, "2.4.", 4)) 1252 return 0; 1253 1254 log_suppress(1); 1255 dm_present = driver_version(vsn, sizeof(vsn)); 1256 log_suppress(0); 1257 1258 if (dm_present || !lvm1_present(cmd)) 1259 return 0; 1260 1261 return 1; 1262 } 1263 1264 static void _exec_lvm1_command(char **argv) 1265 { 1266 char path[PATH_MAX]; 1267 1268 if (dm_snprintf(path, sizeof(path), "%s.lvm1", argv[0]) < 0) { 1269 log_error("Failed to create LVM1 tool pathname"); 1270 return; 1271 } 1272 1273 execvp(path, argv); 1274 log_sys_error("execvp", path); 1275 } 1276 1277 static void _nonroot_warning(void) 1278 { 1279 if (getuid() || geteuid()) 1280 log_warn("WARNING: Running as a non-root user. Functionality may be unavailable."); 1281 } 1282 1283 int lvm2_main(int argc, char **argv) 1284 { 1285 const char *base; 1286 int ret, alias = 0; 1287 struct cmd_context *cmd; 1288 1289 base = last_path_component(argv[0]); 1290 if (strcmp(base, "lvm") && strcmp(base, "lvm.static") && 1291 strcmp(base, "initrd-lvm")) 1292 alias = 1; 1293 1294 _close_stray_fds(base); 1295 1296 if (is_static() && strcmp(base, "lvm.static") && 1297 path_exists(LVM_SHARED_PATH) && 1298 !getenv("LVM_DID_EXEC")) { 1299 setenv("LVM_DID_EXEC", base, 1); 1300 execvp(LVM_SHARED_PATH, argv); 1301 unsetenv("LVM_DID_EXEC"); 1302 } 1303 1304 if (!(cmd = init_lvm())) 1305 return -1; 1306 1307 cmd->argv = argv; 1308 lvm_register_commands(); 1309 1310 if (_lvm1_fallback(cmd)) { 1311 /* Attempt to run equivalent LVM1 tool instead */ 1312 if (!alias) { 1313 argv++; 1314 argc--; 1315 alias = 0; 1316 } 1317 if (!argc) { 1318 log_error("Falling back to LVM1 tools, but no " 1319 "command specified."); 1320 return ECMD_FAILED; 1321 } 1322 _exec_lvm1_command(argv); 1323 return ECMD_FAILED; 1324 } 1325 #ifdef READLINE_SUPPORT 1326 if (!alias && argc == 1) { 1327 _nonroot_warning(); 1328 ret = lvm_shell(cmd, &_cmdline); 1329 goto out; 1330 } 1331 #endif 1332 1333 if (!alias) { 1334 if (argc < 2) { 1335 log_fatal("Please supply an LVM command."); 1336 _display_help(); 1337 ret = EINVALID_CMD_LINE; 1338 goto out; 1339 } 1340 1341 argc--; 1342 argv++; 1343 } 1344 1345 _nonroot_warning(); 1346 ret = lvm_run_command(cmd, argc, argv); 1347 if ((ret == ENO_SUCH_CMD) && (!alias)) 1348 ret = _run_script(cmd, argc, argv); 1349 if (ret == ENO_SUCH_CMD) 1350 log_error("No such command. Try 'help'."); 1351 1352 if ((ret != ECMD_PROCESSED) && !error_message_produced()) { 1353 log_debug("Internal error: Failed command did not use log_error"); 1354 log_error("Command failed with status code %d.", ret); 1355 } 1356 1357 out: 1358 lvm_fin(cmd); 1359 if (ret == ECMD_PROCESSED) 1360 ret = 0; 1361 return ret; 1362 } 1363