1 /* $NetBSD: lvmcmdline.c,v 1.2 2011/01/05 14:57:28 haad Exp $ */ 2 3 /* 4 * Copyright (C) 2001-2004 Sistina Software, Inc. All rights reserved. 5 * Copyright (C) 2004-2009 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 "lvm-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: Move static _the_args into cmd? */ 60 unsigned arg_count(const struct cmd_context *cmd __attribute((unused)), int a) 61 { 62 return _the_args[a].count; 63 } 64 65 unsigned arg_is_set(const struct cmd_context *cmd, int a) 66 { 67 return arg_count(cmd, a) ? 1 : 0; 68 } 69 70 const char *arg_value(struct cmd_context *cmd __attribute((unused)), int a) 71 { 72 return _the_args[a].value; 73 } 74 75 const char *arg_str_value(struct cmd_context *cmd, int a, const char *def) 76 { 77 return arg_count(cmd, a) ? _the_args[a].value : def; 78 } 79 80 int32_t arg_int_value(struct cmd_context *cmd, int a, const int32_t def) 81 { 82 return arg_count(cmd, a) ? _the_args[a].i_value : def; 83 } 84 85 uint32_t arg_uint_value(struct cmd_context *cmd, int a, const uint32_t def) 86 { 87 return arg_count(cmd, a) ? _the_args[a].ui_value : def; 88 } 89 90 int64_t arg_int64_value(struct cmd_context *cmd, int a, const int64_t def) 91 { 92 return arg_count(cmd, a) ? _the_args[a].i64_value : def; 93 } 94 95 uint64_t arg_uint64_value(struct cmd_context *cmd, 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, int a, const void *def) 101 { 102 return arg_count(cmd, a) ? _the_args[a].ptr : def; 103 } 104 105 sign_t arg_sign_value(struct cmd_context *cmd, int a, const sign_t def) 106 { 107 return arg_count(cmd, a) ? _the_args[a].sign : def; 108 } 109 110 percent_t arg_percent_value(struct cmd_context *cmd, int a, const percent_t def) 111 { 112 return arg_count(cmd, a) ? _the_args[a].percent : def; 113 } 114 115 int arg_count_increment(struct cmd_context *cmd __attribute((unused)), int a) 116 { 117 return _the_args[a].count++; 118 } 119 120 int yes_no_arg(struct cmd_context *cmd __attribute((unused)), struct arg *a) 121 { 122 a->sign = SIGN_NONE; 123 a->percent = PERCENT_NONE; 124 125 if (!strcmp(a->value, "y")) { 126 a->i_value = 1; 127 a->ui_value = 1; 128 } 129 130 else if (!strcmp(a->value, "n")) { 131 a->i_value = 0; 132 a->ui_value = 0; 133 } 134 135 else 136 return 0; 137 138 return 1; 139 } 140 141 int yes_no_excl_arg(struct cmd_context *cmd __attribute((unused)), 142 struct arg *a) 143 { 144 a->sign = SIGN_NONE; 145 a->percent = PERCENT_NONE; 146 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; 151 } 152 153 else if (!strcmp(a->value, "y")) { 154 a->i_value = CHANGE_AY; 155 a->ui_value = CHANGE_AY; 156 } 157 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; 162 } 163 164 else if (!strcmp(a->value, "ln") || !strcmp(a->value, "nl")) { 165 a->i_value = CHANGE_ALN; 166 a->ui_value = CHANGE_ALN; 167 } 168 169 else if (!strcmp(a->value, "ly") || !strcmp(a->value, "yl")) { 170 a->i_value = CHANGE_ALY; 171 a->ui_value = CHANGE_ALY; 172 } 173 174 else 175 return 0; 176 177 return 1; 178 } 179 180 int metadatatype_arg(struct cmd_context *cmd, struct arg *a) 181 { 182 struct format_type *fmt; 183 char *format; 184 185 format = a->value; 186 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; 193 } 194 } 195 196 return 0; 197 } 198 199 static int _get_int_arg(struct arg *a, char **ptr) 200 { 201 char *val; 202 long v; 203 204 a->percent = PERCENT_NONE; 205 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; 218 } 219 220 if (!isdigit(*val)) 221 return 0; 222 223 v = strtol(val, ptr, 10); 224 225 if (*ptr == val) 226 return 0; 227 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; 232 233 return 1; 234 } 235 236 /* Size stored in sectors */ 237 static int _size_arg(struct cmd_context *cmd __attribute((unused)), struct arg *a, int factor) 238 { 239 char *ptr; 240 int i; 241 static const char *suffixes = "kmgtpebs"; 242 char *val; 243 double v; 244 uint64_t v_tmp, adjustment; 245 246 a->percent = PERCENT_NONE; 247 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; 260 } 261 262 if (!isdigit(*val)) 263 return 0; 264 265 v = strtod(val, &ptr); 266 267 if (ptr == val) 268 return 0; 269 270 if (*ptr) { 271 for (i = strlen(suffixes) - 1; i >= 0; i--) 272 if (suffixes[i] == tolower((int) *ptr)) 273 break; 274 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; 290 } 291 v /= 512; 292 } else { 293 /* all other units: kmgtpe */ 294 while (i-- > 0) 295 v *= 1024; 296 v *= 2; 297 } 298 } else 299 v *= factor; 300 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; 305 306 return 1; 307 } 308 309 int size_kb_arg(struct cmd_context *cmd, struct arg *a) 310 { 311 return _size_arg(cmd, a, 2); 312 } 313 314 int size_mb_arg(struct cmd_context *cmd, struct arg *a) 315 { 316 return _size_arg(cmd, a, 2048); 317 } 318 319 int int_arg(struct cmd_context *cmd __attribute((unused)), struct arg *a) 320 { 321 char *ptr; 322 323 if (!_get_int_arg(a, &ptr) || (*ptr) || (a->sign == SIGN_MINUS)) 324 return 0; 325 326 return 1; 327 } 328 329 int int_arg_with_sign(struct cmd_context *cmd __attribute((unused)), struct arg *a) 330 { 331 char *ptr; 332 333 if (!_get_int_arg(a, &ptr) || (*ptr)) 334 return 0; 335 336 return 1; 337 } 338 339 int int_arg_with_sign_and_percent(struct cmd_context *cmd __attribute((unused)), 340 struct arg *a) 341 { 342 char *ptr; 343 344 if (!_get_int_arg(a, &ptr)) 345 return 0; 346 347 if (!*ptr) 348 return 1; 349 350 if (*ptr++ != '%') 351 return 0; 352 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; 365 366 return 1; 367 } 368 369 int minor_arg(struct cmd_context *cmd __attribute((unused)), struct arg *a) 370 { 371 char *ptr; 372 373 if (!_get_int_arg(a, &ptr) || (*ptr) || (a->sign == SIGN_MINUS)) 374 return 0; 375 376 if (a->i_value > 255) { 377 log_error("Minor number outside range 0-255"); 378 return 0; 379 } 380 381 return 1; 382 } 383 384 int major_arg(struct cmd_context *cmd __attribute((unused)), struct arg *a) 385 { 386 char *ptr; 387 388 if (!_get_int_arg(a, &ptr) || (*ptr) || (a->sign == SIGN_MINUS)) 389 return 0; 390 391 if (a->i_value > 255) { 392 log_error("Major number outside range 0-255"); 393 return 0; 394 } 395 396 /* FIXME Also Check against /proc/devices */ 397 398 return 1; 399 } 400 401 int string_arg(struct cmd_context *cmd __attribute((unused)), 402 struct arg *a __attribute((unused))) 403 { 404 return 1; 405 } 406 407 int tag_arg(struct cmd_context *cmd __attribute((unused)), struct arg *a) 408 { 409 char *pos = a->value; 410 411 if (*pos == '@') 412 pos++; 413 414 if (!validate_name(pos)) 415 return 0; 416 417 a->value = pos; 418 419 return 1; 420 } 421 422 int permission_arg(struct cmd_context *cmd __attribute((unused)), struct arg *a) 423 { 424 a->sign = SIGN_NONE; 425 426 if ((!strcmp(a->value, "rw")) || (!strcmp(a->value, "wr"))) 427 a->ui_value = LVM_READ | LVM_WRITE; 428 429 else if (!strcmp(a->value, "r")) 430 a->ui_value = LVM_READ; 431 432 else 433 return 0; 434 435 return 1; 436 } 437 438 int alloc_arg(struct cmd_context *cmd __attribute((unused)), struct arg *a) 439 { 440 alloc_policy_t alloc; 441 442 a->sign = SIGN_NONE; 443 444 alloc = get_alloc_from_string(a->value); 445 if (alloc == ALLOC_INVALID) 446 return 0; 447 448 a->ui_value = (uint32_t) alloc; 449 450 return 1; 451 } 452 453 int segtype_arg(struct cmd_context *cmd, struct arg *a) 454 { 455 if (!(a->ptr = (void *) get_segtype_from_string(cmd, a->value))) 456 return 0; 457 458 return 1; 459 } 460 461 /* 462 * Positive integer, zero or "auto". 463 */ 464 int readahead_arg(struct cmd_context *cmd __attribute((unused)), struct arg *a) 465 { 466 if (!strcasecmp(a->value, "auto")) { 467 a->ui_value = DM_READ_AHEAD_AUTO; 468 return 1; 469 } 470 471 if (!strcasecmp(a->value, "none")) { 472 a->ui_value = DM_READ_AHEAD_NONE; 473 return 1; 474 } 475 476 if (!_size_arg(cmd, a, 1)) 477 return 0; 478 479 if (a->sign == SIGN_MINUS) 480 return 0; 481 482 return 1; 483 } 484 485 static void __alloc(int size) 486 { 487 if (!(_cmdline.commands = dm_realloc(_cmdline.commands, sizeof(*_cmdline.commands) * size))) { 488 log_fatal("Couldn't allocate memory."); 489 exit(ECMD_FAILED); 490 } 491 492 _cmdline.commands_size = size; 493 } 494 495 static void _alloc_command(void) 496 { 497 if (!_cmdline.commands_size) 498 __alloc(32); 499 500 if (_cmdline.commands_size <= _cmdline.num_commands) 501 __alloc(2 * _cmdline.commands_size); 502 } 503 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) 508 { 509 struct command *nc; 510 511 _alloc_command(); 512 513 nc = _cmdline.commands + _cmdline.num_commands++; 514 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; 522 } 523 524 static void _register_command(const char *name, command_fn fn, const char *desc, 525 unsigned flags, const char *usagestr, ...) 526 { 527 int nargs = 0, i; 528 int *args; 529 va_list ap; 530 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); 536 537 /* allocate space for them */ 538 if (!(args = dm_malloc(sizeof(*args) * nargs))) { 539 log_fatal("Out of memory."); 540 exit(ECMD_FAILED); 541 } 542 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); 548 549 /* enter the command in the register */ 550 _create_new_command(name, fn, flags, desc, usagestr, nargs, args); 551 } 552 553 void lvm_register_commands(void) 554 { 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 562 } 563 564 static struct command *_find_command(const char *name) 565 { 566 int i; 567 const char *base; 568 569 base = last_path_component(name); 570 571 for (i = 0; i < _cmdline.num_commands; i++) { 572 if (!strcmp(base, _cmdline.commands[i].name)) 573 break; 574 } 575 576 if (i >= _cmdline.num_commands) 577 return 0; 578 579 return _cmdline.commands + i; 580 } 581 582 static void _short_usage(const char *name) 583 { 584 log_error("Run `%s --help' for more information.", name); 585 } 586 587 static int _usage(const char *name) 588 { 589 struct command *com = _find_command(name); 590 591 if (!com) { 592 log_print("%s: no such command.", name); 593 return 0; 594 } 595 596 log_print("%s: %s\n\n%s", com->name, com->desc, com->usage); 597 return 1; 598 } 599 600 /* 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. 606 */ 607 static void _add_getopt_arg(int arg, char **ptr, struct option **o) 608 { 609 struct arg *a = _cmdline.the_args + arg; 610 611 if (a->short_arg) { 612 *(*ptr)++ = a->short_arg; 613 614 if (a->fn) 615 *(*ptr)++ = ':'; 616 } 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)++; 627 } 628 #endif 629 } 630 631 static struct arg *_find_arg(struct command *com, int opt) 632 { 633 struct arg *a; 634 int i, arg; 635 636 for (i = 0; i < com->num_args; i++) { 637 arg = com->valid_args[i]; 638 a = _cmdline.the_args + arg; 639 640 /* 641 * opt should equal either the 642 * short arg, or the index into 643 * the_args. 644 */ 645 if ((a->short_arg && (opt == a->short_arg)) || 646 (!a->short_arg && (opt == arg))) 647 return a; 648 } 649 650 return 0; 651 } 652 653 static int _process_command_line(struct cmd_context *cmd, int *argc, 654 char ***argv) 655 { 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; 660 661 for (i = 0; i < ARG_COUNT; i++) { 662 a = _cmdline.the_args + i; 663 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; 671 } 672 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); 676 677 *ptr = '\0'; 678 memset(o, 0, sizeof(*o)); 679 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) { 684 685 if (opt == '?') 686 return 0; 687 688 a = _find_arg(cmd->command, opt); 689 690 if (!a) { 691 log_fatal("Unrecognised option."); 692 return 0; 693 } 694 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; 702 } 703 704 if (a->fn) { 705 if (!optarg) { 706 log_error("Option requires argument."); 707 return 0; 708 } 709 710 a->value = optarg; 711 712 if (!a->fn(cmd, a)) { 713 log_error("Invalid argument %s", optarg); 714 return 0; 715 } 716 } 717 718 a->count++; 719 } 720 721 *argc -= optind; 722 *argv += optind; 723 return 1; 724 } 725 726 static int _merge_synonym(struct cmd_context *cmd, int oldarg, int newarg) 727 { 728 const struct arg *old; 729 struct arg *new; 730 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; 735 } 736 737 if (!arg_count(cmd, oldarg)) 738 return 1; 739 740 old = _cmdline.the_args + oldarg; 741 new = _cmdline.the_args + newarg; 742 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; 750 751 return 1; 752 } 753 754 int version(struct cmd_context *cmd __attribute((unused)), 755 int argc __attribute((unused)), 756 char **argv __attribute((unused))) 757 { 758 char vsn[80]; 759 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); 765 766 return ECMD_PROCESSED; 767 } 768 769 static int _get_settings(struct cmd_context *cmd) 770 { 771 cmd->current_settings = cmd->default_settings; 772 773 if (arg_count(cmd, debug_ARG)) 774 cmd->current_settings.debug = _LOG_FATAL + 775 (arg_count(cmd, debug_ARG) - 1); 776 777 if (arg_count(cmd, verbose_ARG)) 778 cmd->current_settings.verbose = arg_count(cmd, verbose_ARG); 779 780 if (arg_count(cmd, quiet_ARG)) { 781 cmd->current_settings.debug = 0; 782 cmd->current_settings.verbose = 0; 783 } 784 785 if (arg_count(cmd, test_ARG)) 786 cmd->current_settings.test = arg_count(cmd, test_ARG); 787 788 if (arg_count(cmd, driverloaded_ARG)) { 789 cmd->current_settings.activation = 790 arg_int_value(cmd, driverloaded_ARG, 791 cmd->default_settings.activation); 792 } 793 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; 798 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."); 803 } 804 805 if (arg_count(cmd, ignorelockingfailure_ARG)) 806 init_ignorelockingfailure(1); 807 else 808 init_ignorelockingfailure(0); 809 810 if (arg_count(cmd, nosuffix_ARG)) 811 cmd->current_settings.suffix = 0; 812 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; 819 } 820 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; 825 } 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); 831 832 if (arg_count(cmd, noudevsync_ARG)) 833 cmd->current_settings.udev_sync = 0; 834 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; 842 843 /* Zero indicates success */ 844 return 0; 845 } 846 847 static int _process_common_commands(struct cmd_context *cmd) 848 { 849 if (arg_count(cmd, help_ARG) || arg_count(cmd, help2_ARG)) { 850 _usage(cmd->command->name); 851 return ECMD_PROCESSED; 852 } 853 854 if (arg_count(cmd, version_ARG)) { 855 return version(cmd, 0, (char **) NULL); 856 } 857 858 /* Zero indicates it's OK to continue processing this command */ 859 return 0; 860 } 861 862 static void _display_help(void) 863 { 864 int i; 865 866 log_error("Available lvm commands:"); 867 log_error("Use 'lvm help <command>' for more information"); 868 log_error(" "); 869 870 for (i = 0; i < _cmdline.num_commands; i++) { 871 struct command *com = _cmdline.commands + i; 872 873 log_error("%-16.16s%s", com->name, com->desc); 874 } 875 } 876 877 int help(struct cmd_context *cmd __attribute((unused)), int argc, char **argv) 878 { 879 int ret = ECMD_PROCESSED; 880 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; 888 } 889 890 return ret; 891 } 892 893 static void _apply_settings(struct cmd_context *cmd) 894 { 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); 900 901 init_msg_prefix(cmd->default_settings.msg_prefix); 902 init_cmd_name(cmd->default_settings.cmd_name); 903 904 archive_enable(cmd, cmd->current_settings.archive); 905 backup_enable(cmd, cmd->current_settings.backup); 906 907 set_activation(cmd->current_settings.activation); 908 909 cmd->fmt = arg_ptr_value(cmd, metadatatype_ARG, 910 cmd->current_settings.fmt); 911 cmd->handles_missing_pvs = 0; 912 } 913 914 static const char *_copy_command_line(struct cmd_context *cmd, int argc, char **argv) 915 { 916 int i, space; 917 918 /* 919 * Build up the complete command line, used as a 920 * description for backups. 921 */ 922 if (!dm_pool_begin_object(cmd->mem, 128)) 923 goto_bad; 924 925 for (i = 0; i < argc; i++) { 926 space = strchr(argv[i], ' ') ? 1 : 0; 927 928 if (space && !dm_pool_grow_object(cmd->mem, "'", 1)) 929 goto_bad; 930 931 if (!dm_pool_grow_object(cmd->mem, argv[i], strlen(argv[i]))) 932 goto_bad; 933 934 if (space && !dm_pool_grow_object(cmd->mem, "'", 1)) 935 goto_bad; 936 937 if (i < (argc - 1)) 938 if (!dm_pool_grow_object(cmd->mem, " ", 1)) 939 goto_bad; 940 } 941 942 /* 943 * Terminate. 944 */ 945 if (!dm_pool_grow_object(cmd->mem, "\0", 1)) 946 goto_bad; 947 948 return dm_pool_end_object(cmd->mem); 949 950 bad: 951 log_error("Couldn't copy command line."); 952 dm_pool_abandon_object(cmd->mem); 953 return NULL; 954 } 955 956 int lvm_run_command(struct cmd_context *cmd, int argc, char **argv) 957 { 958 int ret = 0; 959 int locking_type; 960 961 init_error_message_produced(0); 962 963 /* each command should start out with sigint flag cleared */ 964 sigint_clear(); 965 966 if (!(cmd->cmd_line = _copy_command_line(cmd, argc, argv))) { 967 stack; 968 return ECMD_FAILED; 969 } 970 971 log_debug("Parsing: %s", cmd->cmd_line); 972 973 if (!(cmd->command = _find_command(argv[0]))) 974 return ENO_SUCH_CMD; 975 976 if (!_process_command_line(cmd, &argc, &argv)) { 977 log_error("Error during parsing of command line."); 978 return EINVALID_CMD_LINE; 979 } 980 981 set_cmd_name(cmd->command->name); 982 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; 988 } 989 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; 995 } 996 } 997 998 if ((ret = _get_settings(cmd))) 999 goto_out; 1000 _apply_settings(cmd); 1001 1002 log_debug("Processing: %s", cmd->cmd_line); 1003 1004 #ifdef O_DIRECT_SUPPORT 1005 log_debug("O_DIRECT will be used"); 1006 #endif 1007 1008 if ((ret = _process_common_commands(cmd))) 1009 goto_out; 1010 1011 if (arg_count(cmd, nolocking_ARG)) 1012 locking_type = 0; 1013 else 1014 locking_type = -1; 1015 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; 1021 } 1022 1023 ret = cmd->command->fn(cmd, argc, argv); 1024 1025 fin_locking(); 1026 1027 out: 1028 if (test_mode()) { 1029 log_verbose("Test mode: Wiping internal cache"); 1030 lvmcache_destroy(cmd, 1); 1031 } 1032 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; 1039 } 1040 1041 /* FIXME Move this? */ 1042 cmd->current_settings = cmd->default_settings; 1043 _apply_settings(cmd); 1044 1045 if (ret == EINVALID_CMD_LINE && !_cmdline.interactive) 1046 _short_usage(cmd->command->name); 1047 1048 log_debug("Completed: %s", cmd->cmd_line); 1049 1050 /* 1051 * free off any memory the command used. 1052 */ 1053 dm_pool_empty(cmd->mem); 1054 1055 reset_lvm_errno(1); 1056 1057 return ret; 1058 } 1059 1060 int lvm_split(char *str, int *argc, char **argv, int max) 1061 { 1062 char *b = str, *e; 1063 *argc = 0; 1064 1065 while (*b) { 1066 while (*b && isspace(*b)) 1067 b++; 1068 1069 if ((!*b) || (*b == '#')) 1070 break; 1071 1072 e = b; 1073 while (*e && !isspace(*e)) 1074 e++; 1075 1076 argv[(*argc)++] = b; 1077 if (!*e) 1078 break; 1079 *e++ = '\0'; 1080 b = e; 1081 if (*argc == max) 1082 break; 1083 } 1084 1085 return *argc; 1086 } 1087 1088 static const char *_get_cmdline(pid_t pid) 1089 { 1090 static char _proc_cmdline[32]; 1091 char buf[256]; 1092 int fd; 1093 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'; 1101 1102 return _proc_cmdline; 1103 } 1104 1105 static const char *_get_filename(int fd) 1106 { 1107 static char filename[PATH_MAX]; 1108 char buf[32]; /* Assumes short DEFAULT_PROC_DIR */ 1109 int size; 1110 1111 snprintf(buf, sizeof(buf), DEFAULT_PROC_DIR "/self/fd/%u", fd); 1112 1113 if ((size = readlink(buf, filename, sizeof(filename) - 1)) == -1) 1114 filename[0] = '\0'; 1115 else 1116 filename[size] = '\0'; 1117 1118 return filename; 1119 } 1120 1121 static void _close_descriptor(int fd, unsigned suppress_warnings, 1122 const char *command, pid_t ppid, 1123 const char *parent_cmdline) 1124 { 1125 int r; 1126 const char *filename; 1127 1128 /* Ignore bad file descriptors */ 1129 if (fcntl(fd, F_GETFD) == -1 && errno == EBADF) 1130 return; 1131 1132 if (!suppress_warnings) 1133 filename = _get_filename(fd); 1134 1135 r = close(fd); 1136 if (suppress_warnings) 1137 return; 1138 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)); 1147 1148 fprintf(stderr, " Parent PID %" PRIpid_t ": %s\n", ppid, parent_cmdline); 1149 } 1150 1151 static void _close_stray_fds(const char *command) 1152 { 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); 1158 1159 if (getrlimit(RLIMIT_NOFILE, &rlim) < 0) { 1160 fprintf(stderr, "getrlimit(RLIMIT_NOFILE) failed: %s\n", 1161 strerror(errno)); 1162 return; 1163 } 1164 1165 if (getenv("LVM_SUPPRESS_FD_WARNINGS")) 1166 suppress_warnings = 1; 1167 1168 for (fd = 3; fd < rlim.rlim_cur; fd++) 1169 _close_descriptor(fd, suppress_warnings, command, ppid, 1170 parent_cmdline); 1171 } 1172 1173 struct cmd_context *init_lvm(void) 1174 { 1175 struct cmd_context *cmd; 1176 1177 _cmdline.the_args = &_the_args[0]; 1178 1179 if (!(cmd = create_toolcontext(0, NULL))) 1180 return_NULL; 1181 1182 if (stored_errno()) { 1183 destroy_toolcontext(cmd); 1184 return_NULL; 1185 } 1186 1187 return cmd; 1188 } 1189 1190 static void _fin_commands(void) 1191 { 1192 int i; 1193 1194 for (i = 0; i < _cmdline.num_commands; i++) 1195 dm_free(_cmdline.commands[i].valid_args); 1196 1197 dm_free(_cmdline.commands); 1198 } 1199 1200 void lvm_fin(struct cmd_context *cmd) 1201 { 1202 _fin_commands(); 1203 destroy_toolcontext(cmd); 1204 } 1205 1206 static int _run_script(struct cmd_context *cmd, int argc, char **argv) 1207 { 1208 FILE *script; 1209 1210 char buffer[CMD_LEN]; 1211 int ret = 0; 1212 int magic_number = 0; 1213 char *script_file = argv[0]; 1214 1215 if ((script = fopen(script_file, "r")) == NULL) 1216 return ENO_SUCH_CMD; 1217 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; 1225 } 1226 } 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; 1234 } 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; 1240 } 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); 1250 } 1251 break; 1252 } 1253 } 1254 1255 if (fclose(script)) 1256 log_sys_error("fclose", script_file); 1257 1258 return ret; 1259 } 1260 1261 /* 1262 * Determine whether we should fall back and exec the equivalent LVM1 tool 1263 */ 1264 static int _lvm1_fallback(struct cmd_context *cmd) 1265 { 1266 char vsn[80]; 1267 int dm_present; 1268 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; 1273 1274 log_suppress(1); 1275 dm_present = driver_version(vsn, sizeof(vsn)); 1276 log_suppress(0); 1277 1278 if (dm_present || !lvm1_present(cmd)) 1279 return 0; 1280 1281 return 1; 1282 } 1283 1284 static void _exec_lvm1_command(char **argv) 1285 { 1286 char path[PATH_MAX]; 1287 1288 if (dm_snprintf(path, sizeof(path), "%s.lvm1", argv[0]) < 0) { 1289 log_error("Failed to create LVM1 tool pathname"); 1290 return; 1291 } 1292 1293 execvp(path, argv); 1294 log_sys_error("execvp", path); 1295 } 1296 1297 static void _nonroot_warning(void) 1298 { 1299 #ifdef __NetBSD__ 1300 gid_t groups_list[NGROUPS_MAX]; 1301 int i, group_num, is_operator = 0; 1302 1303 /* Operator group in NetBSD should be able to see lvm status. */ 1304 if (getuid() || geteuid()) { 1305 group_num = getgroups(NGROUPS_MAX, groups_list); 1306 1307 for (i = 0; i < group_num; i++) { 1308 if (groups_list[i] == DM_DEVICE_GID) { 1309 is_operator = 1; 1310 init_operator(is_operator); 1311 break; 1312 } 1313 } 1314 1315 if (is_operator) 1316 log_warn("WARNING: Using LVM as operator you have only read access."); 1317 else 1318 log_warn("WARNING: Running as a non-root user and without " 1319 "operator group. Functionality may be unavailable."); 1320 } 1321 #else 1322 if (getuid() || geteuid()) 1323 log_warn("WARNING: Running as a non-root user. Functionality may be unavailable."); 1324 #endif 1325 } 1326 1327 int lvm2_main(int argc, char **argv) 1328 { 1329 const char *base; 1330 int ret, alias = 0; 1331 struct cmd_context *cmd; 1332 1333 base = last_path_component(argv[0]); 1334 if (strcmp(base, "lvm") && strcmp(base, "lvm.static") && 1335 strcmp(base, "initrd-lvm")) 1336 alias = 1; 1337 1338 _close_stray_fds(base); 1339 1340 if (is_static() && strcmp(base, "lvm.static") && 1341 path_exists(LVM_SHARED_PATH) && 1342 !getenv("LVM_DID_EXEC")) { 1343 setenv("LVM_DID_EXEC", base, 1); 1344 execvp(LVM_SHARED_PATH, argv); 1345 unsetenv("LVM_DID_EXEC"); 1346 } 1347 1348 if (!(cmd = init_lvm())) 1349 return -1; 1350 1351 cmd->argv = argv; 1352 lvm_register_commands(); 1353 1354 if (_lvm1_fallback(cmd)) { 1355 /* Attempt to run equivalent LVM1 tool instead */ 1356 if (!alias) { 1357 argv++; 1358 argc--; 1359 alias = 0; 1360 } 1361 if (!argc) { 1362 log_error("Falling back to LVM1 tools, but no " 1363 "command specified."); 1364 return ECMD_FAILED; 1365 } 1366 _exec_lvm1_command(argv); 1367 return ECMD_FAILED; 1368 } 1369 #ifdef READLINE_SUPPORT 1370 if (!alias && argc == 1) { 1371 _nonroot_warning(); 1372 ret = lvm_shell(cmd, &_cmdline); 1373 goto out; 1374 } 1375 #endif 1376 1377 if (!alias) { 1378 if (argc < 2) { 1379 log_fatal("Please supply an LVM command."); 1380 _display_help(); 1381 ret = EINVALID_CMD_LINE; 1382 goto out; 1383 } 1384 1385 argc--; 1386 argv++; 1387 } 1388 1389 _nonroot_warning(); 1390 ret = lvm_run_command(cmd, argc, argv); 1391 if ((ret == ENO_SUCH_CMD) && (!alias)) 1392 ret = _run_script(cmd, argc, argv); 1393 if (ret == ENO_SUCH_CMD) 1394 log_error("No such command. Try 'help'."); 1395 1396 if ((ret != ECMD_PROCESSED) && !error_message_produced()) { 1397 log_debug("Internal error: Failed command did not use log_error"); 1398 log_error("Command failed with status code %d.", ret); 1399 } 1400 1401 out: 1402 lvm_fin(cmd); 1403 if (ret == ECMD_PROCESSED) 1404 ret = 0; 1405 return ret; 1406 } 1407