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