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