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? */
arg_count(const struct cmd_context * cmd __attribute ((unused)),int a)60 unsigned arg_count(const struct cmd_context *cmd __attribute((unused)), int a)
61 {
62           return _the_args[a].count;
63 }
64 
arg_is_set(const struct cmd_context * cmd,int a)65 unsigned arg_is_set(const struct cmd_context *cmd, int a)
66 {
67           return arg_count(cmd, a) ? 1 : 0;
68 }
69 
arg_value(struct cmd_context * cmd __attribute ((unused)),int a)70 const char *arg_value(struct cmd_context *cmd __attribute((unused)), int a)
71 {
72           return _the_args[a].value;
73 }
74 
arg_str_value(struct cmd_context * cmd,int a,const char * def)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 
arg_int_value(struct cmd_context * cmd,int a,const int32_t def)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 
arg_uint_value(struct cmd_context * cmd,int a,const uint32_t def)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 
arg_int64_value(struct cmd_context * cmd,int a,const int64_t def)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 
arg_uint64_value(struct cmd_context * cmd,int a,const uint64_t def)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 
arg_ptr_value(struct cmd_context * cmd,int a,const void * def)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 
arg_sign_value(struct cmd_context * cmd,int a,const sign_t def)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 
arg_percent_value(struct cmd_context * cmd,int a,const percent_t def)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 
arg_count_increment(struct cmd_context * cmd __attribute ((unused)),int a)115 int arg_count_increment(struct cmd_context *cmd __attribute((unused)), int a)
116 {
117           return _the_args[a].count++;
118 }
119 
yes_no_arg(struct cmd_context * cmd __attribute ((unused)),struct arg * a)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 
yes_no_excl_arg(struct cmd_context * cmd __attribute ((unused)),struct arg * a)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 
metadatatype_arg(struct cmd_context * cmd,struct arg * a)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 
_get_int_arg(struct arg * a,char ** ptr)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 */
_size_arg(struct cmd_context * cmd __attribute ((unused)),struct arg * a,int factor)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 
size_kb_arg(struct cmd_context * cmd,struct arg * a)309 int size_kb_arg(struct cmd_context *cmd, struct arg *a)
310 {
311           return _size_arg(cmd, a, 2);
312 }
313 
size_mb_arg(struct cmd_context * cmd,struct arg * a)314 int size_mb_arg(struct cmd_context *cmd, struct arg *a)
315 {
316           return _size_arg(cmd, a, 2048);
317 }
318 
int_arg(struct cmd_context * cmd __attribute ((unused)),struct arg * a)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 
int_arg_with_sign(struct cmd_context * cmd __attribute ((unused)),struct arg * a)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 
int_arg_with_sign_and_percent(struct cmd_context * cmd __attribute ((unused)),struct arg * a)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 
minor_arg(struct cmd_context * cmd __attribute ((unused)),struct arg * a)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 
major_arg(struct cmd_context * cmd __attribute ((unused)),struct arg * a)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 
string_arg(struct cmd_context * cmd __attribute ((unused)),struct arg * a __attribute ((unused)))401 int string_arg(struct cmd_context *cmd __attribute((unused)),
402                  struct arg *a __attribute((unused)))
403 {
404           return 1;
405 }
406 
tag_arg(struct cmd_context * cmd __attribute ((unused)),struct arg * a)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 
permission_arg(struct cmd_context * cmd __attribute ((unused)),struct arg * a)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 
alloc_arg(struct cmd_context * cmd __attribute ((unused)),struct arg * a)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 
segtype_arg(struct cmd_context * cmd,struct arg * a)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  */
readahead_arg(struct cmd_context * cmd __attribute ((unused)),struct arg * a)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 
__alloc(int size)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 
_alloc_command(void)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 
_create_new_command(const char * name,command_fn command,unsigned flags,const char * desc,const char * usagestr,int nargs,int * args)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 
_register_command(const char * name,command_fn fn,const char * desc,unsigned flags,const char * usagestr,...)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 
lvm_register_commands(void)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 
_find_command(const char * name)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 
_short_usage(const char * name)582 static void _short_usage(const char *name)
583 {
584           log_error("Run `%s --help' for more information.", name);
585 }
586 
_usage(const char * name)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  */
_add_getopt_arg(int arg,char ** ptr,struct option ** o)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 
_find_arg(struct command * com,int opt)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 
_process_command_line(struct cmd_context * cmd,int * argc,char *** argv)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 
_merge_synonym(struct cmd_context * cmd,int oldarg,int newarg)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 
version(struct cmd_context * cmd __attribute ((unused)),int argc __attribute ((unused)),char ** argv __attribute ((unused)))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 
_get_settings(struct cmd_context * cmd)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 
_process_common_commands(struct cmd_context * cmd)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 
_display_help(void)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 
help(struct cmd_context * cmd __attribute ((unused)),int argc,char ** argv)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 
_apply_settings(struct cmd_context * cmd)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 
_copy_command_line(struct cmd_context * cmd,int argc,char ** argv)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 
lvm_run_command(struct cmd_context * cmd,int argc,char ** argv)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 
lvm_split(char * str,int * argc,char ** argv,int max)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 
_get_cmdline(pid_t pid)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 
_get_filename(int fd)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 
_close_descriptor(int fd,unsigned suppress_warnings,const char * command,pid_t ppid,const char * parent_cmdline)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 
_close_stray_fds(const char * command)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 
init_lvm(void)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 
_fin_commands(void)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 
lvm_fin(struct cmd_context * cmd)1200 void lvm_fin(struct cmd_context *cmd)
1201 {
1202           _fin_commands();
1203           destroy_toolcontext(cmd);
1204 }
1205 
_run_script(struct cmd_context * cmd,int argc,char ** argv)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  */
_lvm1_fallback(struct cmd_context * cmd)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 
_exec_lvm1_command(char ** argv)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 
_nonroot_warning(void)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 
lvm2_main(int argc,char ** argv)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