]>
Commit | Line | Data |
---|---|---|
dcc31da5 | 1 | /* |
67cdbd7e | 2 | * Copyright (C) 2003-2004 Sistina Software, Inc. All rights reserved. |
ec647f1d | 3 | * Copyright (C) 2004-2015 Red Hat, Inc. All rights reserved. |
dcc31da5 | 4 | * |
6606c3ae | 5 | * This file is part of LVM2. |
dcc31da5 | 6 | * |
6606c3ae AK |
7 | * This copyrighted material is made available to anyone wishing to use, |
8 | * modify, copy, or redistribute it subject to the terms and conditions | |
be684599 | 9 | * of the GNU Lesser General Public License v.2.1. |
dcc31da5 | 10 | * |
be684599 | 11 | * You should have received a copy of the GNU Lesser General Public License |
6606c3ae | 12 | * along with this program; if not, write to the Free Software Foundation, |
fcbef05a | 13 | * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA |
dcc31da5 AK |
14 | */ |
15 | ||
16 | #include "tools.h" | |
17 | ||
5ed7d0cf | 18 | static int _get_vsn(struct cmd_context *cmd, uint16_t *version_int) |
34350963 | 19 | { |
ec647f1d | 20 | const char *vsn; |
f5584d42 | 21 | unsigned int major, minor, patchlevel; |
34350963 | 22 | |
bbf574ab ZK |
23 | if (!(vsn = arg_str_value(cmd, atversion_ARG, NULL)) && |
24 | !(vsn = arg_str_value(cmd, sinceversion_ARG, NULL))) | |
ec647f1d | 25 | vsn = LVM_VERSION; |
1ea8afd3 | 26 | |
ec647f1d | 27 | if (sscanf(vsn, "%u.%u.%u", &major, &minor, &patchlevel) != 3) { |
34350963 PR |
28 | log_error("Incorrect version format."); |
29 | return 0; | |
30 | } | |
31 | ||
5ed7d0cf | 32 | *version_int = vsn(major, minor, patchlevel); |
34350963 PR |
33 | return 1; |
34 | } | |
35 | ||
5dcec173 PR |
36 | static int _do_def_check(struct config_def_tree_spec *spec, |
37 | struct dm_config_tree *cft, | |
5ed7d0cf | 38 | struct cft_check_handle **cft_check_handle) |
661406a4 PR |
39 | { |
40 | struct cft_check_handle *handle; | |
41 | ||
c42f7286 | 42 | if (!(handle = get_config_tree_check_handle(spec->cmd, cft))) |
661406a4 PR |
43 | return 0; |
44 | ||
45 | handle->force_check = 1; | |
661406a4 PR |
46 | handle->suppress_messages = 1; |
47 | ||
24f32721 PR |
48 | if (spec->type == CFG_DEF_TREE_DIFF) { |
49 | if (!handle->check_diff) | |
50 | handle->skip_if_checked = 0; | |
5dcec173 | 51 | handle->check_diff = 1; |
24f32721 | 52 | } else { |
5dcec173 | 53 | handle->skip_if_checked = 1; |
24f32721 PR |
54 | handle->check_diff = 0; |
55 | } | |
5dcec173 | 56 | |
8b6b90b0 PR |
57 | handle->ignoreunsupported = spec->ignoreunsupported; |
58 | handle->ignoreadvanced = spec->ignoreadvanced; | |
59 | ||
000e81a9 | 60 | config_def_check(handle); |
661406a4 PR |
61 | *cft_check_handle = handle; |
62 | ||
63 | return 1; | |
64 | } | |
65 | ||
5ed7d0cf PR |
66 | static int _merge_config_cascade(struct cmd_context *cmd, struct dm_config_tree *cft_cascaded, |
67 | struct dm_config_tree **cft_merged) | |
68 | { | |
69 | if (!cft_cascaded) | |
70 | return 1; | |
71 | ||
72 | if (!*cft_merged && !(*cft_merged = config_open(CONFIG_MERGED_FILES, NULL, 0))) | |
73 | return_0; | |
74 | ||
75 | if (!_merge_config_cascade(cmd, cft_cascaded->cascade, cft_merged)) | |
76 | return_0; | |
77 | ||
78 | return merge_config_tree(cmd, *cft_merged, cft_cascaded, CONFIG_MERGE_TYPE_RAW); | |
79 | } | |
80 | ||
c42f7286 PR |
81 | static int _config_validate(struct cmd_context *cmd, struct dm_config_tree *cft) |
82 | { | |
83 | struct cft_check_handle *handle; | |
84 | ||
85 | if (!(handle = get_config_tree_check_handle(cmd, cft))) | |
86 | return 1; | |
87 | ||
88 | handle->force_check = 1; | |
89 | handle->skip_if_checked = 1; | |
90 | handle->suppress_messages = 0; | |
91 | ||
92 | return config_def_check(handle); | |
93 | } | |
94 | ||
dcc31da5 AK |
95 | int dumpconfig(struct cmd_context *cmd, int argc, char **argv) |
96 | { | |
a8fb89ad | 97 | const char *file = arg_str_value(cmd, file_ARG, NULL); |
7e671e5d | 98 | const char *type = arg_str_value(cmd, configtype_ARG, arg_is_set(cmd, list_ARG) ? "list" : "current"); |
34350963 | 99 | struct config_def_tree_spec tree_spec = {0}; |
f5584d42 | 100 | struct dm_config_tree *cft = NULL; |
661406a4 | 101 | struct cft_check_handle *cft_check_handle = NULL; |
9c937e7d | 102 | struct profile *profile = NULL; |
34350963 PR |
103 | int r = ECMD_PROCESSED; |
104 | ||
b53ec372 PR |
105 | tree_spec.cmd = cmd; |
106 | ||
7e671e5d | 107 | if (arg_is_set(cmd, configtype_ARG) && arg_is_set(cmd, validate_ARG)) { |
34350963 PR |
108 | log_error("Only one of --type and --validate permitted."); |
109 | return EINVALID_CMD_LINE; | |
110 | } | |
111 | ||
7e671e5d | 112 | if (arg_is_set(cmd, configtype_ARG) && arg_is_set(cmd, list_ARG)) { |
3be3eb29 PR |
113 | log_error("Only one of --type and --list permitted."); |
114 | return EINVALID_CMD_LINE; | |
115 | } | |
116 | ||
7e671e5d AK |
117 | if (arg_is_set(cmd, atversion_ARG)) { |
118 | if (arg_is_set(cmd, sinceversion_ARG)) { | |
1ea8afd3 PR |
119 | log_error("Only one of --atversion and --sinceversion permitted."); |
120 | return EINVALID_CMD_LINE; | |
121 | } | |
122 | ||
7e671e5d | 123 | if (!arg_is_set(cmd, configtype_ARG) && !arg_is_set(cmd, list_ARG)) { |
1ea8afd3 PR |
124 | log_error("--atversion requires --type or --list"); |
125 | return EINVALID_CMD_LINE; | |
126 | } | |
7e671e5d AK |
127 | } else if (arg_is_set(cmd, sinceversion_ARG)) { |
128 | if (!arg_is_set(cmd, configtype_ARG) || strcmp(type, "new")) { | |
1ea8afd3 PR |
129 | log_error("--sinceversion requires --type new"); |
130 | return EINVALID_CMD_LINE; | |
131 | } | |
34350963 PR |
132 | } |
133 | ||
7e671e5d | 134 | if (arg_is_set(cmd, ignoreadvanced_ARG)) |
7d6991e9 PR |
135 | tree_spec.ignoreadvanced = 1; |
136 | ||
7e671e5d AK |
137 | if (arg_is_set(cmd, ignoreunsupported_ARG)) { |
138 | if (arg_is_set(cmd, showunsupported_ARG)) { | |
8b6b90b0 PR |
139 | log_error("Only one of --ignoreunsupported and --showunsupported permitted."); |
140 | return EINVALID_CMD_LINE; | |
141 | } | |
7d6991e9 | 142 | tree_spec.ignoreunsupported = 1; |
7e671e5d | 143 | } else if (arg_is_set(cmd, showunsupported_ARG)) { |
8b6b90b0 PR |
144 | tree_spec.ignoreunsupported = 0; |
145 | } else if (strcmp(type, "current") && strcmp(type, "diff")) { | |
146 | /* | |
147 | * By default hide unsupported settings | |
148 | * for all display types except "current" | |
149 | * and "diff". | |
150 | */ | |
151 | tree_spec.ignoreunsupported = 1; | |
152 | } | |
7d6991e9 | 153 | |
fc65269d PR |
154 | if (strcmp(type, "current") && strcmp(type, "diff")) { |
155 | /* | |
156 | * By default hide deprecated settings | |
157 | * for all display types except "current" | |
158 | * and "diff" unless --showdeprecated is set. | |
159 | * | |
160 | * N.B. Deprecated settings are visible if | |
161 | * --atversion is used with a version that | |
162 | * is lower than the version in which the | |
163 | * setting was deprecated. | |
164 | */ | |
7e671e5d | 165 | if (!arg_is_set(cmd, showdeprecated_ARG)) |
fc65269d PR |
166 | tree_spec.ignoredeprecated = 1; |
167 | } | |
168 | ||
7e671e5d | 169 | if (arg_is_set(cmd, ignorelocal_ARG)) |
9b86e8e8 DT |
170 | tree_spec.ignorelocal = 1; |
171 | ||
c794c163 | 172 | if (!strcmp(type, "current") || !strcmp(type, "full")) { |
7e671e5d | 173 | if (arg_is_set(cmd, atversion_ARG)) { |
c794c163 | 174 | log_error("--atversion has no effect with --type %s", type); |
f5584d42 PR |
175 | return EINVALID_CMD_LINE; |
176 | } | |
177 | ||
7e671e5d AK |
178 | if ((arg_is_set(cmd, ignoreunsupported_ARG) || |
179 | arg_is_set(cmd, ignoreadvanced_ARG)) && | |
c794c163 | 180 | !strcmp(type, "current")) { |
8b6b90b0 | 181 | /* FIXME: allow these even for --type current */ |
f5584d42 PR |
182 | log_error("--ignoreadvanced and --ignoreunsupported has " |
183 | "no effect with --type current"); | |
184 | return EINVALID_CMD_LINE; | |
185 | } | |
7e671e5d | 186 | } else if (arg_is_set(cmd, mergedconfig_ARG)) { |
c794c163 | 187 | log_error("--mergedconfig has no effect without --type current or --type full"); |
25f5e2da | 188 | return EINVALID_CMD_LINE; |
f5584d42 PR |
189 | } |
190 | ||
191 | if (!_get_vsn(cmd, &tree_spec.version)) | |
192 | return EINVALID_CMD_LINE; | |
193 | ||
9c937e7d PR |
194 | /* |
195 | * The profile specified by --profile cmd arg is like --commandprofile, | |
196 | * but it is used just for dumping the profile content and not for | |
197 | * application. | |
198 | */ | |
7e671e5d | 199 | if (arg_is_set(cmd, profile_ARG) && |
9c937e7d PR |
200 | (!(profile = add_profile(cmd, arg_str_value(cmd, profile_ARG, NULL), CONFIG_PROFILE_COMMAND)) || |
201 | !override_config_tree_from_profile(cmd, profile))) { | |
202 | log_error("Failed to load profile %s.", arg_str_value(cmd, profile_ARG, NULL)); | |
203 | return ECMD_FAILED; | |
204 | } | |
205 | ||
5ed7d0cf PR |
206 | /* |
207 | * Set the 'cft' to work with based on whether we need the plain | |
208 | * config tree or merged config tree cascade if --mergedconfig is used. | |
209 | */ | |
7e671e5d | 210 | if ((arg_is_set(cmd, mergedconfig_ARG) || !strcmp(type, "full") || !strcmp(type, "diff")) && cmd->cft->cascade) { |
5ed7d0cf PR |
211 | if (!_merge_config_cascade(cmd, cmd->cft, &cft)) { |
212 | log_error("Failed to merge configuration."); | |
213 | r = ECMD_FAILED; | |
214 | goto out; | |
215 | } | |
216 | } else | |
217 | cft = cmd->cft; | |
c794c163 | 218 | tree_spec.current_cft = cft; |
5ed7d0cf | 219 | |
7e671e5d | 220 | if (arg_is_set(cmd, validate_ARG)) { |
c42f7286 | 221 | if (_config_validate(cmd, cft)) { |
34350963 | 222 | log_print("LVM configuration valid."); |
5ed7d0cf | 223 | goto out; |
34350963 PR |
224 | } else { |
225 | log_error("LVM configuration invalid."); | |
5ed7d0cf PR |
226 | r = ECMD_FAILED; |
227 | goto out; | |
34350963 PR |
228 | } |
229 | } | |
230 | ||
7e671e5d | 231 | if (!strcmp(type, "list") || arg_is_set(cmd, list_ARG)) { |
3be3eb29 | 232 | tree_spec.type = CFG_DEF_TREE_LIST; |
7e671e5d | 233 | if (arg_is_set(cmd, withcomments_ARG)) { |
3be3eb29 PR |
234 | log_error("--withcomments has no effect with --type list"); |
235 | return EINVALID_CMD_LINE; | |
236 | } | |
fe423ef5 AK |
237 | if (arg_is_set(cmd, withlocalpreamble_ARG)) { |
238 | log_error("--withlocalpreamble has no effect with --type list"); | |
239 | return EINVALID_CMD_LINE; | |
240 | } | |
241 | if (arg_is_set(cmd, withgeneralpreamble_ARG)) { | |
242 | log_error("--withgeneralpreamble has no effect with --type list"); | |
243 | return EINVALID_CMD_LINE; | |
244 | } | |
b4cc28c2 PR |
245 | if (arg_is_set(cmd, valuesonly_ARG)) { |
246 | log_err("--valuesonly has no effect with --type list"); | |
247 | return EINVALID_CMD_LINE; | |
248 | } | |
3be3eb29 | 249 | /* list type does not require status check */ |
c794c163 PR |
250 | } else if (!strcmp(type, "full")) { |
251 | tree_spec.type = CFG_DEF_TREE_FULL; | |
252 | if (!_do_def_check(&tree_spec, cft, &cft_check_handle)) { | |
253 | r = ECMD_FAILED; | |
254 | goto_out; | |
255 | } | |
3be3eb29 | 256 | } else if (!strcmp(type, "current")) { |
34350963 | 257 | tree_spec.type = CFG_DEF_TREE_CURRENT; |
5dcec173 | 258 | if (!_do_def_check(&tree_spec, cft, &cft_check_handle)) { |
5ed7d0cf PR |
259 | r = ECMD_FAILED; |
260 | goto_out; | |
261 | } | |
34350963 | 262 | } |
661406a4 | 263 | else if (!strcmp(type, "missing")) { |
34350963 | 264 | tree_spec.type = CFG_DEF_TREE_MISSING; |
5dcec173 | 265 | if (!_do_def_check(&tree_spec, cft, &cft_check_handle)) { |
5ed7d0cf PR |
266 | r = ECMD_FAILED; |
267 | goto_out; | |
268 | } | |
661406a4 PR |
269 | } |
270 | else if (!strcmp(type, "default")) { | |
271 | tree_spec.type = CFG_DEF_TREE_DEFAULT; | |
272 | /* default type does not require check status */ | |
273 | } | |
5dcec173 PR |
274 | else if (!strcmp(type, "diff")) { |
275 | tree_spec.type = CFG_DEF_TREE_DIFF; | |
276 | if (!_do_def_check(&tree_spec, cft, &cft_check_handle)) { | |
277 | r = ECMD_FAILED; | |
278 | goto_out; | |
279 | } | |
280 | } | |
661406a4 | 281 | else if (!strcmp(type, "new")) { |
7e671e5d | 282 | tree_spec.type = arg_is_set(cmd, sinceversion_ARG) ? CFG_DEF_TREE_NEW_SINCE |
1ea8afd3 | 283 | : CFG_DEF_TREE_NEW; |
661406a4 PR |
284 | /* new type does not require check status */ |
285 | } | |
953a438e PR |
286 | else if (!strcmp(type, "profilable")) { |
287 | tree_spec.type = CFG_DEF_TREE_PROFILABLE; | |
288 | /* profilable type does not require check status */ | |
289 | } | |
9c937e7d PR |
290 | else if (!strcmp(type, "profilable-command")) { |
291 | tree_spec.type = CFG_DEF_TREE_PROFILABLE_CMD; | |
292 | /* profilable-command type does not require check status */ | |
293 | } | |
294 | else if (!strcmp(type, "profilable-metadata")) { | |
295 | tree_spec.type = CFG_DEF_TREE_PROFILABLE_MDA; | |
296 | /* profilable-metadata type does not require check status */ | |
297 | } | |
34350963 PR |
298 | else { |
299 | log_error("Incorrect type of configuration specified. " | |
c794c163 PR |
300 | "Expected one of: current, default, diff, full, list, missing, " |
301 | "new, profilable, profilable-command, profilable-metadata."); | |
5ed7d0cf PR |
302 | r = EINVALID_CMD_LINE; |
303 | goto out; | |
34350963 PR |
304 | } |
305 | ||
7e671e5d | 306 | if (arg_is_set(cmd, withsummary_ARG) || arg_is_set(cmd, list_ARG)) |
0ba332e8 | 307 | tree_spec.withsummary = 1; |
fe423ef5 | 308 | |
7e671e5d | 309 | if (arg_is_set(cmd, withcomments_ARG)) |
558c9324 | 310 | tree_spec.withcomments = 1; |
fe423ef5 | 311 | |
7e671e5d | 312 | if (arg_is_set(cmd, unconfigured_ARG)) |
5cd63817 | 313 | tree_spec.unconfigured = 1; |
558c9324 | 314 | |
7e671e5d | 315 | if (arg_is_set(cmd, withversions_ARG)) |
558c9324 PR |
316 | tree_spec.withversions = 1; |
317 | ||
fe423ef5 AK |
318 | if (arg_is_set(cmd, withgeneralpreamble_ARG)) |
319 | tree_spec.withgeneralpreamble = 1; | |
320 | ||
321 | if (arg_is_set(cmd, withlocalpreamble_ARG)) | |
322 | tree_spec.withlocalpreamble = 1; | |
323 | ||
7e671e5d | 324 | if (arg_is_set(cmd, withspaces_ARG)) |
a4724350 PR |
325 | tree_spec.withspaces = 1; |
326 | ||
b4cc28c2 PR |
327 | if (arg_is_set(cmd, valuesonly_ARG)) |
328 | tree_spec.valuesonly = 1; | |
329 | ||
661406a4 PR |
330 | if (cft_check_handle) |
331 | tree_spec.check_status = cft_check_handle->status; | |
332 | ||
c394c2a6 | 333 | if ((tree_spec.type != CFG_DEF_TREE_CURRENT) && |
5dcec173 | 334 | (tree_spec.type != CFG_DEF_TREE_DIFF) && |
c394c2a6 ZK |
335 | !(cft = config_def_create_tree(&tree_spec))) { |
336 | r = ECMD_FAILED; | |
337 | goto_out; | |
338 | } | |
34350963 | 339 | |
558c9324 | 340 | if (!config_write(cft, &tree_spec, file, argc, argv)) { |
651ff9b3 | 341 | stack; |
34350963 | 342 | r = ECMD_FAILED; |
651ff9b3 | 343 | } |
5ed7d0cf | 344 | out: |
c794c163 PR |
345 | if (tree_spec.current_cft && (tree_spec.current_cft != cft) && |
346 | (tree_spec.current_cft != cmd->cft)) | |
347 | /* | |
348 | * This happens in case of CFG_DEF_TREE_FULL where we | |
349 | * have merged explicitly defined config trees and also | |
350 | * we have used default tree. | |
351 | */ | |
352 | dm_config_destroy(tree_spec.current_cft); | |
353 | ||
5ed7d0cf | 354 | if (cft && (cft != cmd->cft)) |
c794c163 | 355 | dm_config_destroy(cft); |
9c937e7d PR |
356 | else if (profile) |
357 | remove_config_tree_by_source(cmd, CONFIG_PROFILE_COMMAND); | |
34350963 | 358 | |
f5584d42 PR |
359 | /* |
360 | * The cmd->cft (the "current" tree) is destroyed | |
361 | * together with cmd context destroy... | |
362 | */ | |
363 | ||
34350963 | 364 | return r; |
dcc31da5 | 365 | } |
3f043405 AK |
366 | |
367 | int config(struct cmd_context *cmd, int argc, char **argv) | |
368 | { | |
369 | return dumpconfig(cmd, argc, argv); | |
370 | } | |
371 | ||
372 | int lvmconfig(struct cmd_context *cmd, int argc, char **argv) | |
373 | { | |
374 | return dumpconfig(cmd, argc, argv); | |
375 | } |