xref: /dflybsd-src/contrib/lvm2/dist/lib/commands/toolcontext.c (revision bf0d92b7fe9456dcf7fead1088076021bf662363)
1d6f15486SAlex Hornung /*	$NetBSD: toolcontext.c,v 1.7 2009/12/05 01:52:44 haad Exp $	*/
2d6f15486SAlex Hornung 
3d6f15486SAlex Hornung /*
4d6f15486SAlex Hornung  * Copyright (C) 2001-2004 Sistina Software, Inc. All rights reserved.
5d6f15486SAlex Hornung  * Copyright (C) 2004-2009 Red Hat, Inc. All rights reserved.
6d6f15486SAlex Hornung  *
7d6f15486SAlex Hornung  * This file is part of LVM2.
8d6f15486SAlex Hornung  *
9d6f15486SAlex Hornung  * This copyrighted material is made available to anyone wishing to use,
10d6f15486SAlex Hornung  * modify, copy, or redistribute it subject to the terms and conditions
11d6f15486SAlex Hornung  * of the GNU Lesser General Public License v.2.1.
12d6f15486SAlex Hornung  *
13d6f15486SAlex Hornung  * You should have received a copy of the GNU Lesser General Public License
14d6f15486SAlex Hornung  * along with this program; if not, write to the Free Software Foundation,
15d6f15486SAlex Hornung  * Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
16d6f15486SAlex Hornung  */
17d6f15486SAlex Hornung 
18d6f15486SAlex Hornung #include "lib.h"
19d6f15486SAlex Hornung #include "toolcontext.h"
20d6f15486SAlex Hornung #include "metadata.h"
21d6f15486SAlex Hornung #include "defaults.h"
22d6f15486SAlex Hornung #include "lvm-string.h"
23d6f15486SAlex Hornung #include "activate.h"
24d6f15486SAlex Hornung #include "filter.h"
25d6f15486SAlex Hornung #include "filter-composite.h"
26d6f15486SAlex Hornung #include "filter-md.h"
27d6f15486SAlex Hornung #include "filter-persistent.h"
28d6f15486SAlex Hornung #include "filter-regex.h"
29d6f15486SAlex Hornung #include "filter-sysfs.h"
30d6f15486SAlex Hornung #include "label.h"
31d6f15486SAlex Hornung #include "lvm-file.h"
32d6f15486SAlex Hornung #include "format-text.h"
33d6f15486SAlex Hornung #include "display.h"
34d6f15486SAlex Hornung #include "memlock.h"
35d6f15486SAlex Hornung #include "str_list.h"
36d6f15486SAlex Hornung #include "segtype.h"
37d6f15486SAlex Hornung #include "lvmcache.h"
38d6f15486SAlex Hornung #include "dev-cache.h"
39d6f15486SAlex Hornung #include "archiver.h"
40d6f15486SAlex Hornung 
41d6f15486SAlex Hornung #ifdef HAVE_LIBDL
42d6f15486SAlex Hornung #include "sharedlib.h"
43d6f15486SAlex Hornung #endif
44d6f15486SAlex Hornung 
45d6f15486SAlex Hornung #ifdef LVM1_INTERNAL
46d6f15486SAlex Hornung #include "format1.h"
47d6f15486SAlex Hornung #endif
48d6f15486SAlex Hornung 
49d6f15486SAlex Hornung #ifdef POOL_INTERNAL
50d6f15486SAlex Hornung #include "format_pool.h"
51d6f15486SAlex Hornung #endif
52d6f15486SAlex Hornung 
53d6f15486SAlex Hornung #include <locale.h>
54d6f15486SAlex Hornung #include <sys/stat.h>
55d6f15486SAlex Hornung #include <sys/utsname.h>
56d6f15486SAlex Hornung #include <syslog.h>
57d6f15486SAlex Hornung #include <time.h>
58*bf0d92b7SSascha Wildner #include <unistd.h>
59d6f15486SAlex Hornung 
60d6f15486SAlex Hornung #ifdef linux
61d6f15486SAlex Hornung #  include <malloc.h>
62d6f15486SAlex Hornung #endif
63d6f15486SAlex Hornung 
_get_env_vars(struct cmd_context * cmd)64d6f15486SAlex Hornung static int _get_env_vars(struct cmd_context *cmd)
65d6f15486SAlex Hornung {
66d6f15486SAlex Hornung 	const char *e;
67d6f15486SAlex Hornung 
68d6f15486SAlex Hornung 	/* Set to "" to avoid using any system directory */
69d6f15486SAlex Hornung 	if ((e = getenv("LVM_SYSTEM_DIR"))) {
70d6f15486SAlex Hornung 		if (dm_snprintf(cmd->system_dir, sizeof(cmd->system_dir),
71d6f15486SAlex Hornung 				 "%s", e) < 0) {
72d6f15486SAlex Hornung 			log_error("LVM_SYSTEM_DIR environment variable "
73d6f15486SAlex Hornung 				  "is too long.");
74d6f15486SAlex Hornung 			return 0;
75d6f15486SAlex Hornung 		}
76d6f15486SAlex Hornung 	}
77d6f15486SAlex Hornung 
78d6f15486SAlex Hornung 	return 1;
79d6f15486SAlex Hornung }
80d6f15486SAlex Hornung 
_get_sysfs_dir(struct cmd_context * cmd)81d6f15486SAlex Hornung static void _get_sysfs_dir(struct cmd_context *cmd)
82d6f15486SAlex Hornung {
83d6f15486SAlex Hornung 	static char proc_mounts[PATH_MAX];
84d6f15486SAlex Hornung 	static char *split[4], buffer[PATH_MAX + 16];
85d6f15486SAlex Hornung 	FILE *fp;
86d6f15486SAlex Hornung 	char *sys_mnt = NULL;
87d6f15486SAlex Hornung 
88d6f15486SAlex Hornung 	cmd->sysfs_dir[0] = '\0';
89d6f15486SAlex Hornung 	if (!*cmd->proc_dir) {
90d6f15486SAlex Hornung 		log_debug("No proc filesystem found: skipping sysfs detection");
91d6f15486SAlex Hornung 		return;
92d6f15486SAlex Hornung 	}
93d6f15486SAlex Hornung 
94d6f15486SAlex Hornung 	if (dm_snprintf(proc_mounts, sizeof(proc_mounts),
95d6f15486SAlex Hornung 			 "%s/mounts", cmd->proc_dir) < 0) {
96d6f15486SAlex Hornung 		log_error("Failed to create /proc/mounts string for sysfs detection");
97d6f15486SAlex Hornung 		return;
98d6f15486SAlex Hornung 	}
99d6f15486SAlex Hornung 
100d6f15486SAlex Hornung 	if (!(fp = fopen(proc_mounts, "r"))) {
101d6f15486SAlex Hornung 		log_sys_error("_get_sysfs_dir: fopen %s", proc_mounts);
102d6f15486SAlex Hornung 		return;
103d6f15486SAlex Hornung 	}
104d6f15486SAlex Hornung 
105d6f15486SAlex Hornung 	while (fgets(buffer, sizeof(buffer), fp)) {
106d6f15486SAlex Hornung 		if (dm_split_words(buffer, 4, 0, split) == 4 &&
107d6f15486SAlex Hornung 		    !strcmp(split[2], "sysfs")) {
108d6f15486SAlex Hornung 			sys_mnt = split[1];
109d6f15486SAlex Hornung 			break;
110d6f15486SAlex Hornung 		}
111d6f15486SAlex Hornung 	}
112d6f15486SAlex Hornung 
113d6f15486SAlex Hornung 	if (fclose(fp))
114d6f15486SAlex Hornung 		log_sys_error("fclose", proc_mounts);
115d6f15486SAlex Hornung 
116d6f15486SAlex Hornung 	if (!sys_mnt) {
117d6f15486SAlex Hornung 		log_error("Failed to find sysfs mount point");
118d6f15486SAlex Hornung 		return;
119d6f15486SAlex Hornung 	}
120d6f15486SAlex Hornung 
121d6f15486SAlex Hornung 	strncpy(cmd->sysfs_dir, sys_mnt, sizeof(cmd->sysfs_dir));
122d6f15486SAlex Hornung }
123d6f15486SAlex Hornung 
_init_logging(struct cmd_context * cmd)124d6f15486SAlex Hornung static void _init_logging(struct cmd_context *cmd)
125d6f15486SAlex Hornung {
126d6f15486SAlex Hornung 	int append = 1;
127d6f15486SAlex Hornung 	time_t t;
128d6f15486SAlex Hornung 
129d6f15486SAlex Hornung 	const char *log_file;
130d6f15486SAlex Hornung 	char timebuf[26];
131d6f15486SAlex Hornung 
132d6f15486SAlex Hornung 	/* Syslog */
133d6f15486SAlex Hornung 	cmd->default_settings.syslog =
134d6f15486SAlex Hornung 	    find_config_tree_int(cmd, "log/syslog", DEFAULT_SYSLOG);
135d6f15486SAlex Hornung 	if (cmd->default_settings.syslog != 1)
136d6f15486SAlex Hornung 		fin_syslog();
137d6f15486SAlex Hornung 
138d6f15486SAlex Hornung 	if (cmd->default_settings.syslog > 1)
139d6f15486SAlex Hornung 		init_syslog(cmd->default_settings.syslog);
140d6f15486SAlex Hornung 
141d6f15486SAlex Hornung 	/* Debug level for log file output */
142d6f15486SAlex Hornung 	cmd->default_settings.debug =
143d6f15486SAlex Hornung 	    find_config_tree_int(cmd, "log/level", DEFAULT_LOGLEVEL);
144d6f15486SAlex Hornung 	init_debug(cmd->default_settings.debug);
145d6f15486SAlex Hornung 
146d6f15486SAlex Hornung 	/* Verbose level for tty output */
147d6f15486SAlex Hornung 	cmd->default_settings.verbose =
148d6f15486SAlex Hornung 	    find_config_tree_int(cmd, "log/verbose", DEFAULT_VERBOSE);
149d6f15486SAlex Hornung 	init_verbose(cmd->default_settings.verbose + VERBOSE_BASE_LEVEL);
150d6f15486SAlex Hornung 
151d6f15486SAlex Hornung 	/* Log message formatting */
152d6f15486SAlex Hornung 	init_indent(find_config_tree_int(cmd, "log/indent",
153d6f15486SAlex Hornung 				    DEFAULT_INDENT));
154d6f15486SAlex Hornung 
155d6f15486SAlex Hornung 	cmd->default_settings.msg_prefix = find_config_tree_str(cmd,
156d6f15486SAlex Hornung 							   "log/prefix",
157d6f15486SAlex Hornung 							   DEFAULT_MSG_PREFIX);
158d6f15486SAlex Hornung 	init_msg_prefix(cmd->default_settings.msg_prefix);
159d6f15486SAlex Hornung 
160d6f15486SAlex Hornung 	cmd->default_settings.cmd_name = find_config_tree_int(cmd,
161d6f15486SAlex Hornung 							 "log/command_names",
162d6f15486SAlex Hornung 							 DEFAULT_CMD_NAME);
163d6f15486SAlex Hornung 	init_cmd_name(cmd->default_settings.cmd_name);
164d6f15486SAlex Hornung 
165d6f15486SAlex Hornung 	/* Test mode */
166d6f15486SAlex Hornung 	cmd->default_settings.test =
167d6f15486SAlex Hornung 	    find_config_tree_int(cmd, "global/test", 0);
168d6f15486SAlex Hornung 	init_test(cmd->default_settings.test);
169d6f15486SAlex Hornung 
170d6f15486SAlex Hornung 	/* Settings for logging to file */
171d6f15486SAlex Hornung 	if (find_config_tree_int(cmd, "log/overwrite", DEFAULT_OVERWRITE))
172d6f15486SAlex Hornung 		append = 0;
173d6f15486SAlex Hornung 
174d6f15486SAlex Hornung 	log_file = find_config_tree_str(cmd, "log/file", 0);
175d6f15486SAlex Hornung 
176d6f15486SAlex Hornung 	if (log_file) {
177d6f15486SAlex Hornung 		release_log_memory();
178d6f15486SAlex Hornung 		fin_log();
179d6f15486SAlex Hornung 		init_log_file(log_file, append);
180d6f15486SAlex Hornung 	}
181d6f15486SAlex Hornung 
182d6f15486SAlex Hornung 	log_file = find_config_tree_str(cmd, "log/activate_file", 0);
183d6f15486SAlex Hornung 	if (log_file)
184d6f15486SAlex Hornung 		init_log_direct(log_file, append);
185d6f15486SAlex Hornung 
186d6f15486SAlex Hornung 	init_log_while_suspended(find_config_tree_int(cmd,
187d6f15486SAlex Hornung 						 "log/activation", 0));
188d6f15486SAlex Hornung 
189d6f15486SAlex Hornung 	t = time(NULL);
190d6f15486SAlex Hornung 	ctime_r(&t, &timebuf[0]);
191d6f15486SAlex Hornung 	timebuf[24] = '\0';
192d6f15486SAlex Hornung 	log_verbose("Logging initialised at %s", timebuf);
193d6f15486SAlex Hornung 
194d6f15486SAlex Hornung 	/* Tell device-mapper about our logging */
195d6f15486SAlex Hornung #ifdef DEVMAPPER_SUPPORT
196d6f15486SAlex Hornung 	dm_log_with_errno_init(print_log);
197d6f15486SAlex Hornung #endif
198d6f15486SAlex Hornung }
199d6f15486SAlex Hornung 
_process_config(struct cmd_context * cmd)200d6f15486SAlex Hornung static int _process_config(struct cmd_context *cmd)
201d6f15486SAlex Hornung {
202d6f15486SAlex Hornung 	mode_t old_umask;
203d6f15486SAlex Hornung 	const char *read_ahead;
204d6f15486SAlex Hornung 	struct stat st;
205d6f15486SAlex Hornung 
206d6f15486SAlex Hornung 	/* umask */
207d6f15486SAlex Hornung 	cmd->default_settings.umask = find_config_tree_int(cmd,
208d6f15486SAlex Hornung 						      "global/umask",
209d6f15486SAlex Hornung 						      DEFAULT_UMASK);
210d6f15486SAlex Hornung 
211d6f15486SAlex Hornung 	if ((old_umask = umask((mode_t) cmd->default_settings.umask)) !=
212d6f15486SAlex Hornung 	    (mode_t) cmd->default_settings.umask)
213d6f15486SAlex Hornung 		log_verbose("Set umask to %04o", cmd->default_settings.umask);
214d6f15486SAlex Hornung 
215d6f15486SAlex Hornung 	/* dev dir */
216d6f15486SAlex Hornung 	if (dm_snprintf(cmd->dev_dir, sizeof(cmd->dev_dir), "%s/",
217d6f15486SAlex Hornung 			 find_config_tree_str(cmd, "devices/dir",
218d6f15486SAlex Hornung 					 DEFAULT_DEV_DIR)) < 0) {
219d6f15486SAlex Hornung 		log_error("Device directory given in config file too long");
220d6f15486SAlex Hornung 		return 0;
221d6f15486SAlex Hornung 	}
222d6f15486SAlex Hornung #ifdef DEVMAPPER_SUPPORT
223d6f15486SAlex Hornung 	dm_set_dev_dir(cmd->dev_dir);
224d6f15486SAlex Hornung #endif
2252bc6f059SAlex Hornung #if !defined(__NetBSD__) && !defined(__DragonFly__)
226d6f15486SAlex Hornung 	/* proc dir */
227d6f15486SAlex Hornung 	if (dm_snprintf(cmd->proc_dir, sizeof(cmd->proc_dir), "%s",
228d6f15486SAlex Hornung 			 find_config_tree_str(cmd, "global/proc",
229d6f15486SAlex Hornung 					 DEFAULT_PROC_DIR)) < 0) {
230d6f15486SAlex Hornung 		log_error("Device directory given in config file too long");
231d6f15486SAlex Hornung 		return 0;
232d6f15486SAlex Hornung 	}
233d6f15486SAlex Hornung #endif
234d6f15486SAlex Hornung 	if (*cmd->proc_dir && !dir_exists(cmd->proc_dir)) {
235d6f15486SAlex Hornung 		log_error("WARNING: proc dir %s not found - some checks will be bypassed",
236d6f15486SAlex Hornung 			  cmd->proc_dir);
237d6f15486SAlex Hornung 		*cmd->proc_dir = '\0';
238d6f15486SAlex Hornung 	}
239d6f15486SAlex Hornung 
240d6f15486SAlex Hornung 	_get_sysfs_dir(cmd);
241d6f15486SAlex Hornung 
242d6f15486SAlex Hornung 	/* activation? */
243d6f15486SAlex Hornung 	cmd->default_settings.activation = find_config_tree_int(cmd,
244d6f15486SAlex Hornung 							   "global/activation",
245d6f15486SAlex Hornung 							   DEFAULT_ACTIVATION);
246d6f15486SAlex Hornung 	set_activation(cmd->default_settings.activation);
247d6f15486SAlex Hornung 
248d6f15486SAlex Hornung 	cmd->default_settings.suffix = find_config_tree_int(cmd,
249d6f15486SAlex Hornung 						       "global/suffix",
250d6f15486SAlex Hornung 						       DEFAULT_SUFFIX);
251d6f15486SAlex Hornung 
252d6f15486SAlex Hornung 	if (!(cmd->default_settings.unit_factor =
253d6f15486SAlex Hornung 	      units_to_bytes(find_config_tree_str(cmd,
254d6f15486SAlex Hornung 					     "global/units",
255d6f15486SAlex Hornung 					     DEFAULT_UNITS),
256d6f15486SAlex Hornung 			     &cmd->default_settings.unit_type))) {
257d6f15486SAlex Hornung 		log_error("Invalid units specification");
258d6f15486SAlex Hornung 		return 0;
259d6f15486SAlex Hornung 	}
260d6f15486SAlex Hornung 
261d6f15486SAlex Hornung 	read_ahead = find_config_tree_str(cmd, "activation/readahead", DEFAULT_READ_AHEAD);
262d6f15486SAlex Hornung 	if (!strcasecmp(read_ahead, "auto"))
263d6f15486SAlex Hornung 		cmd->default_settings.read_ahead = DM_READ_AHEAD_AUTO;
264d6f15486SAlex Hornung 	else if (!strcasecmp(read_ahead, "none"))
265d6f15486SAlex Hornung 		cmd->default_settings.read_ahead = DM_READ_AHEAD_NONE;
266d6f15486SAlex Hornung 	else {
267d6f15486SAlex Hornung 		log_error("Invalid readahead specification");
268d6f15486SAlex Hornung 		return 0;
269d6f15486SAlex Hornung 	}
270d6f15486SAlex Hornung 
271d6f15486SAlex Hornung 	cmd->default_settings.udev_sync = find_config_tree_int(cmd,
272d6f15486SAlex Hornung 								"activation/udev_sync",
273d6f15486SAlex Hornung 								DEFAULT_UDEV_SYNC);
274d6f15486SAlex Hornung 
275d6f15486SAlex Hornung 	cmd->stripe_filler = find_config_tree_str(cmd,
276d6f15486SAlex Hornung 						  "activation/missing_stripe_filler",
277d6f15486SAlex Hornung 						  DEFAULT_STRIPE_FILLER);
278d6f15486SAlex Hornung 
279d6f15486SAlex Hornung 	/* FIXME Missing error code checks from the stats, not log_warn?, notify if setting overridden, delay message/check till it is actually used (eg consider if lvm shell - file could appear later after this check)? */
280d6f15486SAlex Hornung 	if (!strcmp(cmd->stripe_filler, "/dev/ioerror") &&
281d6f15486SAlex Hornung 	    stat(cmd->stripe_filler, &st))
282d6f15486SAlex Hornung 		cmd->stripe_filler = "error";
283d6f15486SAlex Hornung 
284d6f15486SAlex Hornung 	if (strcmp(cmd->stripe_filler, "error")) {
285d6f15486SAlex Hornung 		if (stat(cmd->stripe_filler, &st)) {
286d6f15486SAlex Hornung 			log_warn("WARNING: activation/missing_stripe_filler = \"%s\" "
287d6f15486SAlex Hornung 				 "is invalid,", cmd->stripe_filler);
288d6f15486SAlex Hornung 			log_warn("         stat failed: %s", strerror(errno));
289d6f15486SAlex Hornung 			log_warn("Falling back to \"error\" missing_stripe_filler.");
290d6f15486SAlex Hornung 			cmd->stripe_filler = "error";
291d6f15486SAlex Hornung 		} else if (!S_ISBLK(st.st_mode)) {
292d6f15486SAlex Hornung 			log_warn("WARNING: activation/missing_stripe_filler = \"%s\" "
293d6f15486SAlex Hornung 				 "is not a block device.", cmd->stripe_filler);
294d6f15486SAlex Hornung 			log_warn("Falling back to \"error\" missing_stripe_filler.");
295d6f15486SAlex Hornung 			cmd->stripe_filler = "error";
296d6f15486SAlex Hornung 		}
297d6f15486SAlex Hornung 	}
298d6f15486SAlex Hornung 
299d6f15486SAlex Hornung 	cmd->si_unit_consistency = find_config_tree_int(cmd,
300d6f15486SAlex Hornung 						  "global/si_unit_consistency",
301d6f15486SAlex Hornung 						  DEFAULT_SI_UNIT_CONSISTENCY);
302d6f15486SAlex Hornung 
303d6f15486SAlex Hornung 	return 1;
304d6f15486SAlex Hornung }
305d6f15486SAlex Hornung 
_set_tag(struct cmd_context * cmd,const char * tag)306d6f15486SAlex Hornung static int _set_tag(struct cmd_context *cmd, const char *tag)
307d6f15486SAlex Hornung {
308d6f15486SAlex Hornung 	log_very_verbose("Setting host tag: %s", dm_pool_strdup(cmd->libmem, tag));
309d6f15486SAlex Hornung 
310d6f15486SAlex Hornung 	if (!str_list_add(cmd->libmem, &cmd->tags, tag)) {
311d6f15486SAlex Hornung 		log_error("_set_tag: str_list_add %s failed", tag);
312d6f15486SAlex Hornung 		return 0;
313d6f15486SAlex Hornung 	}
314d6f15486SAlex Hornung 
315d6f15486SAlex Hornung 	return 1;
316d6f15486SAlex Hornung }
317d6f15486SAlex Hornung 
_check_host_filters(struct cmd_context * cmd,struct config_node * hn,int * passes)318d6f15486SAlex Hornung static int _check_host_filters(struct cmd_context *cmd, struct config_node *hn,
319d6f15486SAlex Hornung 			       int *passes)
320d6f15486SAlex Hornung {
321d6f15486SAlex Hornung 	struct config_node *cn;
322d6f15486SAlex Hornung 	struct config_value *cv;
323d6f15486SAlex Hornung 
324d6f15486SAlex Hornung 	*passes = 1;
325d6f15486SAlex Hornung 
326d6f15486SAlex Hornung 	for (cn = hn; cn; cn = cn->sib) {
327d6f15486SAlex Hornung 		if (!cn->v)
328d6f15486SAlex Hornung 			continue;
329d6f15486SAlex Hornung 		if (!strcmp(cn->key, "host_list")) {
330d6f15486SAlex Hornung 			*passes = 0;
331d6f15486SAlex Hornung 			if (cn->v->type == CFG_EMPTY_ARRAY)
332d6f15486SAlex Hornung 				continue;
333d6f15486SAlex Hornung 			for (cv = cn->v; cv; cv = cv->next) {
334d6f15486SAlex Hornung 				if (cv->type != CFG_STRING) {
335d6f15486SAlex Hornung 					log_error("Invalid hostname string "
336d6f15486SAlex Hornung 						  "for tag %s", cn->key);
337d6f15486SAlex Hornung 					return 0;
338d6f15486SAlex Hornung 				}
339d6f15486SAlex Hornung 				if (!strcmp(cv->v.str, cmd->hostname)) {
340d6f15486SAlex Hornung 					*passes = 1;
341d6f15486SAlex Hornung 					return 1;
342d6f15486SAlex Hornung 				}
343d6f15486SAlex Hornung 			}
344d6f15486SAlex Hornung 		}
345d6f15486SAlex Hornung 		if (!strcmp(cn->key, "host_filter")) {
346d6f15486SAlex Hornung 			log_error("host_filter not supported yet");
347d6f15486SAlex Hornung 			return 0;
348d6f15486SAlex Hornung 		}
349d6f15486SAlex Hornung 	}
350d6f15486SAlex Hornung 
351d6f15486SAlex Hornung 	return 1;
352d6f15486SAlex Hornung }
353d6f15486SAlex Hornung 
_init_tags(struct cmd_context * cmd,struct config_tree * cft)354d6f15486SAlex Hornung static int _init_tags(struct cmd_context *cmd, struct config_tree *cft)
355d6f15486SAlex Hornung {
356d6f15486SAlex Hornung 	const struct config_node *tn, *cn;
357d6f15486SAlex Hornung 	const char *tag;
358d6f15486SAlex Hornung 	int passes;
359d6f15486SAlex Hornung 
360d6f15486SAlex Hornung 	if (!(tn = find_config_node(cft->root, "tags")) || !tn->child)
361d6f15486SAlex Hornung 		return 1;
362d6f15486SAlex Hornung 
363d6f15486SAlex Hornung 	/* NB hosttags 0 when already 1 intentionally does not delete the tag */
364d6f15486SAlex Hornung 	if (!cmd->hosttags && find_config_int(cft->root, "tags/hosttags",
365d6f15486SAlex Hornung 					      DEFAULT_HOSTTAGS)) {
366d6f15486SAlex Hornung 		/* FIXME Strip out invalid chars: only A-Za-z0-9_+.- */
367d6f15486SAlex Hornung 		if (!_set_tag(cmd, cmd->hostname))
368d6f15486SAlex Hornung 			return_0;
369d6f15486SAlex Hornung 		cmd->hosttags = 1;
370d6f15486SAlex Hornung 	}
371d6f15486SAlex Hornung 
372d6f15486SAlex Hornung 	for (cn = tn->child; cn; cn = cn->sib) {
373d6f15486SAlex Hornung 		if (cn->v)
374d6f15486SAlex Hornung 			continue;
375d6f15486SAlex Hornung 		tag = cn->key;
376d6f15486SAlex Hornung 		if (*tag == '@')
377d6f15486SAlex Hornung 			tag++;
378d6f15486SAlex Hornung 		if (!validate_name(tag)) {
379d6f15486SAlex Hornung 			log_error("Invalid tag in config file: %s", cn->key);
380d6f15486SAlex Hornung 			return 0;
381d6f15486SAlex Hornung 		}
382d6f15486SAlex Hornung 		if (cn->child) {
383d6f15486SAlex Hornung 			passes = 0;
384d6f15486SAlex Hornung 			if (!_check_host_filters(cmd, cn->child, &passes))
385d6f15486SAlex Hornung 				return_0;
386d6f15486SAlex Hornung 			if (!passes)
387d6f15486SAlex Hornung 				continue;
388d6f15486SAlex Hornung 		}
389d6f15486SAlex Hornung 		if (!_set_tag(cmd, tag))
390d6f15486SAlex Hornung 			return_0;
391d6f15486SAlex Hornung 	}
392d6f15486SAlex Hornung 
393d6f15486SAlex Hornung 	return 1;
394d6f15486SAlex Hornung }
395d6f15486SAlex Hornung 
_load_config_file(struct cmd_context * cmd,const char * tag)396d6f15486SAlex Hornung static int _load_config_file(struct cmd_context *cmd, const char *tag)
397d6f15486SAlex Hornung {
398d6f15486SAlex Hornung 	char config_file[PATH_MAX] = "";
399d6f15486SAlex Hornung 	const char *filler = "";
400d6f15486SAlex Hornung 	struct stat info;
401d6f15486SAlex Hornung 	struct config_tree_list *cfl;
402d6f15486SAlex Hornung 
403d6f15486SAlex Hornung 	if (*tag)
404d6f15486SAlex Hornung 		filler = "_";
405d6f15486SAlex Hornung 
406d6f15486SAlex Hornung 	if (dm_snprintf(config_file, sizeof(config_file), "%s/lvm%s%s.conf",
407d6f15486SAlex Hornung 			 cmd->system_dir, filler, tag) < 0) {
408d6f15486SAlex Hornung 		log_error("LVM_SYSTEM_DIR or tag was too long");
409d6f15486SAlex Hornung 		return 0;
410d6f15486SAlex Hornung 	}
411d6f15486SAlex Hornung 
412d6f15486SAlex Hornung 	if (!(cfl = dm_pool_alloc(cmd->libmem, sizeof(*cfl)))) {
413d6f15486SAlex Hornung 		log_error("config_tree_list allocation failed");
414d6f15486SAlex Hornung 		return 0;
415d6f15486SAlex Hornung 	}
416d6f15486SAlex Hornung 
417d6f15486SAlex Hornung 	if (!(cfl->cft = create_config_tree(config_file, 0))) {
418d6f15486SAlex Hornung 		log_error("config_tree allocation failed");
419d6f15486SAlex Hornung 		return 0;
420d6f15486SAlex Hornung 	}
421d6f15486SAlex Hornung 
422d6f15486SAlex Hornung 	/* Is there a config file? */
423d6f15486SAlex Hornung 	if (stat(config_file, &info) == -1) {
424d6f15486SAlex Hornung 		if (errno == ENOENT) {
425d6f15486SAlex Hornung 			dm_list_add(&cmd->config_files, &cfl->list);
426d6f15486SAlex Hornung 			goto out;
427d6f15486SAlex Hornung 		}
428d6f15486SAlex Hornung 		log_sys_error("stat", config_file);
429d6f15486SAlex Hornung 		destroy_config_tree(cfl->cft);
430d6f15486SAlex Hornung 		return 0;
431d6f15486SAlex Hornung 	}
432d6f15486SAlex Hornung 
433d6f15486SAlex Hornung 	log_very_verbose("Loading config file: %s", config_file);
434d6f15486SAlex Hornung 	if (!read_config_file(cfl->cft)) {
435d6f15486SAlex Hornung 		log_error("Failed to load config file %s", config_file);
436d6f15486SAlex Hornung 		destroy_config_tree(cfl->cft);
437d6f15486SAlex Hornung 		return 0;
438d6f15486SAlex Hornung 	}
439d6f15486SAlex Hornung 
440d6f15486SAlex Hornung 	dm_list_add(&cmd->config_files, &cfl->list);
441d6f15486SAlex Hornung 
442d6f15486SAlex Hornung       out:
443d6f15486SAlex Hornung 	if (*tag)
444d6f15486SAlex Hornung 		_init_tags(cmd, cfl->cft);
445d6f15486SAlex Hornung 	else
446d6f15486SAlex Hornung 		/* Use temporary copy of lvm.conf while loading other files */
447d6f15486SAlex Hornung 		cmd->cft = cfl->cft;
448d6f15486SAlex Hornung 
449d6f15486SAlex Hornung 	return 1;
450d6f15486SAlex Hornung }
451d6f15486SAlex Hornung 
452d6f15486SAlex Hornung /* Find and read first config file */
_init_lvm_conf(struct cmd_context * cmd)453d6f15486SAlex Hornung static int _init_lvm_conf(struct cmd_context *cmd)
454d6f15486SAlex Hornung {
455d6f15486SAlex Hornung 	/* No config file if LVM_SYSTEM_DIR is empty */
456d6f15486SAlex Hornung 	if (!*cmd->system_dir) {
457d6f15486SAlex Hornung 		if (!(cmd->cft = create_config_tree(NULL, 0))) {
458d6f15486SAlex Hornung 			log_error("Failed to create config tree");
459d6f15486SAlex Hornung 			return 0;
460d6f15486SAlex Hornung 		}
461d6f15486SAlex Hornung 		return 1;
462d6f15486SAlex Hornung 	}
463d6f15486SAlex Hornung 
464d6f15486SAlex Hornung 	if (!_load_config_file(cmd, ""))
465d6f15486SAlex Hornung 		return_0;
466d6f15486SAlex Hornung 
467d6f15486SAlex Hornung 	return 1;
468d6f15486SAlex Hornung }
469d6f15486SAlex Hornung 
470d6f15486SAlex Hornung /* Read any additional config files */
_init_tag_configs(struct cmd_context * cmd)471d6f15486SAlex Hornung static int _init_tag_configs(struct cmd_context *cmd)
472d6f15486SAlex Hornung {
473d6f15486SAlex Hornung 	struct str_list *sl;
474d6f15486SAlex Hornung 
475d6f15486SAlex Hornung 	/* Tag list may grow while inside this loop */
476d6f15486SAlex Hornung 	dm_list_iterate_items(sl, &cmd->tags) {
477d6f15486SAlex Hornung 		if (!_load_config_file(cmd, sl->str))
478d6f15486SAlex Hornung 			return_0;
479d6f15486SAlex Hornung 	}
480d6f15486SAlex Hornung 
481d6f15486SAlex Hornung 	return 1;
482d6f15486SAlex Hornung }
483d6f15486SAlex Hornung 
_merge_config_files(struct cmd_context * cmd)484d6f15486SAlex Hornung static int _merge_config_files(struct cmd_context *cmd)
485d6f15486SAlex Hornung {
486d6f15486SAlex Hornung 	struct config_tree_list *cfl;
487d6f15486SAlex Hornung 
488d6f15486SAlex Hornung 	/* Replace temporary duplicate copy of lvm.conf */
489d6f15486SAlex Hornung 	if (cmd->cft->root) {
490d6f15486SAlex Hornung 		if (!(cmd->cft = create_config_tree(NULL, 0))) {
491d6f15486SAlex Hornung 			log_error("Failed to create config tree");
492d6f15486SAlex Hornung 			return 0;
493d6f15486SAlex Hornung 		}
494d6f15486SAlex Hornung 	}
495d6f15486SAlex Hornung 
496d6f15486SAlex Hornung 	dm_list_iterate_items(cfl, &cmd->config_files) {
497d6f15486SAlex Hornung 		/* Merge all config trees into cmd->cft using merge/tag rules */
498d6f15486SAlex Hornung 		if (!merge_config_tree(cmd, cmd->cft, cfl->cft))
499d6f15486SAlex Hornung 			return_0;
500d6f15486SAlex Hornung 	}
501d6f15486SAlex Hornung 
502d6f15486SAlex Hornung 	return 1;
503d6f15486SAlex Hornung }
504d6f15486SAlex Hornung 
_destroy_tags(struct cmd_context * cmd)505d6f15486SAlex Hornung static void _destroy_tags(struct cmd_context *cmd)
506d6f15486SAlex Hornung {
507d6f15486SAlex Hornung 	struct dm_list *slh, *slht;
508d6f15486SAlex Hornung 
509d6f15486SAlex Hornung 	dm_list_iterate_safe(slh, slht, &cmd->tags) {
510d6f15486SAlex Hornung 		dm_list_del(slh);
511d6f15486SAlex Hornung 	}
512d6f15486SAlex Hornung }
513d6f15486SAlex Hornung 
config_files_changed(struct cmd_context * cmd)514d6f15486SAlex Hornung int config_files_changed(struct cmd_context *cmd)
515d6f15486SAlex Hornung {
516d6f15486SAlex Hornung 	struct config_tree_list *cfl;
517d6f15486SAlex Hornung 
518d6f15486SAlex Hornung 	dm_list_iterate_items(cfl, &cmd->config_files) {
519d6f15486SAlex Hornung 		if (config_file_changed(cfl->cft))
520d6f15486SAlex Hornung 			return 1;
521d6f15486SAlex Hornung 	}
522d6f15486SAlex Hornung 
523d6f15486SAlex Hornung 	return 0;
524d6f15486SAlex Hornung }
525d6f15486SAlex Hornung 
_destroy_tag_configs(struct cmd_context * cmd)526d6f15486SAlex Hornung static void _destroy_tag_configs(struct cmd_context *cmd)
527d6f15486SAlex Hornung {
528d6f15486SAlex Hornung 	struct config_tree_list *cfl;
529d6f15486SAlex Hornung 
530d6f15486SAlex Hornung 	dm_list_iterate_items(cfl, &cmd->config_files) {
531d6f15486SAlex Hornung 		if (cfl->cft == cmd->cft)
532d6f15486SAlex Hornung 			cmd->cft = NULL;
533d6f15486SAlex Hornung 		destroy_config_tree(cfl->cft);
534d6f15486SAlex Hornung 	}
535d6f15486SAlex Hornung 
536d6f15486SAlex Hornung 	if (cmd->cft) {
537d6f15486SAlex Hornung 		destroy_config_tree(cmd->cft);
538d6f15486SAlex Hornung 		cmd->cft = NULL;
539d6f15486SAlex Hornung 	}
540d6f15486SAlex Hornung 
541d6f15486SAlex Hornung 	dm_list_init(&cmd->config_files);
542d6f15486SAlex Hornung }
543d6f15486SAlex Hornung 
_init_dev_cache(struct cmd_context * cmd)544d6f15486SAlex Hornung static int _init_dev_cache(struct cmd_context *cmd)
545d6f15486SAlex Hornung {
546d6f15486SAlex Hornung 	const struct config_node *cn;
547d6f15486SAlex Hornung 	struct config_value *cv;
548d6f15486SAlex Hornung 
549d6f15486SAlex Hornung 	if (!dev_cache_init(cmd))
550d6f15486SAlex Hornung 		return_0;
551d6f15486SAlex Hornung 
552d6f15486SAlex Hornung 	if (!(cn = find_config_tree_node(cmd, "devices/scan"))) {
553d6f15486SAlex Hornung 		if (!dev_cache_add_dir("/dev")) {
554d6f15486SAlex Hornung 			log_error("Failed to add /dev to internal "
555d6f15486SAlex Hornung 				  "device cache");
556d6f15486SAlex Hornung 			return 0;
557d6f15486SAlex Hornung 		}
558d6f15486SAlex Hornung 		log_verbose("device/scan not in config file: "
559d6f15486SAlex Hornung 			    "Defaulting to /dev");
560d6f15486SAlex Hornung 		return 1;
561d6f15486SAlex Hornung 	}
562d6f15486SAlex Hornung 
563d6f15486SAlex Hornung 	for (cv = cn->v; cv; cv = cv->next) {
564d6f15486SAlex Hornung 		if (cv->type != CFG_STRING) {
565d6f15486SAlex Hornung 			log_error("Invalid string in config file: "
566d6f15486SAlex Hornung 				  "devices/scan");
567d6f15486SAlex Hornung 			return 0;
568d6f15486SAlex Hornung 		}
569d6f15486SAlex Hornung 
570d6f15486SAlex Hornung 		if (!dev_cache_add_dir(cv->v.str)) {
571d6f15486SAlex Hornung 			log_error("Failed to add %s to internal device cache",
572d6f15486SAlex Hornung 				  cv->v.str);
573d6f15486SAlex Hornung 			return 0;
574d6f15486SAlex Hornung 		}
575d6f15486SAlex Hornung 	}
576d6f15486SAlex Hornung 
577d6f15486SAlex Hornung 	if (!(cn = find_config_tree_node(cmd, "devices/loopfiles")))
578d6f15486SAlex Hornung 		return 1;
579d6f15486SAlex Hornung 
580d6f15486SAlex Hornung 	for (cv = cn->v; cv; cv = cv->next) {
581d6f15486SAlex Hornung 		if (cv->type != CFG_STRING) {
582d6f15486SAlex Hornung 			log_error("Invalid string in config file: "
583d6f15486SAlex Hornung 				  "devices/loopfiles");
584d6f15486SAlex Hornung 			return 0;
585d6f15486SAlex Hornung 		}
586d6f15486SAlex Hornung 
587d6f15486SAlex Hornung 		if (!dev_cache_add_loopfile(cv->v.str)) {
588d6f15486SAlex Hornung 			log_error("Failed to add loopfile %s to internal "
589d6f15486SAlex Hornung 				  "device cache", cv->v.str);
590d6f15486SAlex Hornung 			return 0;
591d6f15486SAlex Hornung 		}
592d6f15486SAlex Hornung 	}
593d6f15486SAlex Hornung 
594d6f15486SAlex Hornung 
595d6f15486SAlex Hornung 	return 1;
596d6f15486SAlex Hornung }
597d6f15486SAlex Hornung 
598d6f15486SAlex Hornung #define MAX_FILTERS 4
599d6f15486SAlex Hornung 
_init_filter_components(struct cmd_context * cmd)600d6f15486SAlex Hornung static struct dev_filter *_init_filter_components(struct cmd_context *cmd)
601d6f15486SAlex Hornung {
602d6f15486SAlex Hornung 	unsigned nr_filt = 0;
603d6f15486SAlex Hornung 	const struct config_node *cn;
604d6f15486SAlex Hornung 	struct dev_filter *filters[MAX_FILTERS];
605d6f15486SAlex Hornung 
606d6f15486SAlex Hornung 	memset(filters, 0, sizeof(filters));
607d6f15486SAlex Hornung 
608d6f15486SAlex Hornung 	/*
609d6f15486SAlex Hornung 	 * Filters listed in order: top one gets applied first.
610d6f15486SAlex Hornung 	 * Failure to initialise some filters is not fatal.
611d6f15486SAlex Hornung 	 * Update MAX_FILTERS definition above when adding new filters.
612d6f15486SAlex Hornung 	 */
613d6f15486SAlex Hornung 
614d6f15486SAlex Hornung 	/*
615d6f15486SAlex Hornung 	 * sysfs filter. Only available on 2.6 kernels.  Non-critical.
616d6f15486SAlex Hornung 	 * Listed first because it's very efficient at eliminating
617d6f15486SAlex Hornung 	 * unavailable devices.
618d6f15486SAlex Hornung 	 */
619d6f15486SAlex Hornung 	if (find_config_tree_bool(cmd, "devices/sysfs_scan",
620d6f15486SAlex Hornung 			     DEFAULT_SYSFS_SCAN)) {
621d6f15486SAlex Hornung 		if ((filters[nr_filt] = sysfs_filter_create(cmd->sysfs_dir)))
622d6f15486SAlex Hornung 			nr_filt++;
623d6f15486SAlex Hornung 	}
624d6f15486SAlex Hornung 
625d6f15486SAlex Hornung 	/* regex filter. Optional. */
626d6f15486SAlex Hornung 	if (!(cn = find_config_tree_node(cmd, "devices/filter")))
627d6f15486SAlex Hornung 		log_very_verbose("devices/filter not found in config file: "
628d6f15486SAlex Hornung 				 "no regex filter installed");
629d6f15486SAlex Hornung 
630d6f15486SAlex Hornung 	else if (!(filters[nr_filt++] = regex_filter_create(cn->v))) {
631d6f15486SAlex Hornung 		log_error("Failed to create regex device filter");
632d6f15486SAlex Hornung 		return NULL;
633d6f15486SAlex Hornung 	}
634d6f15486SAlex Hornung 
635d6f15486SAlex Hornung 	/* device type filter. Required. */
636d6f15486SAlex Hornung 	cn = find_config_tree_node(cmd, "devices/types");
637d6f15486SAlex Hornung 	if (!(filters[nr_filt++] = lvm_type_filter_create(cmd->proc_dir, cn))) {
638d6f15486SAlex Hornung 		log_error("Failed to create lvm type filter");
639d6f15486SAlex Hornung 		return NULL;
640d6f15486SAlex Hornung 	}
641d6f15486SAlex Hornung 
642d6f15486SAlex Hornung 	/* md component filter. Optional, non-critical. */
643d6f15486SAlex Hornung 	if (find_config_tree_bool(cmd, "devices/md_component_detection",
644d6f15486SAlex Hornung 			     DEFAULT_MD_COMPONENT_DETECTION)) {
645d6f15486SAlex Hornung 		init_md_filtering(1);
646d6f15486SAlex Hornung 		if ((filters[nr_filt] = md_filter_create()))
647d6f15486SAlex Hornung 			nr_filt++;
648d6f15486SAlex Hornung 	}
649d6f15486SAlex Hornung 
650d6f15486SAlex Hornung 	/* Only build a composite filter if we really need it. */
651d6f15486SAlex Hornung 	return (nr_filt == 1) ?
652d6f15486SAlex Hornung 	    filters[0] : composite_filter_create(nr_filt, filters);
653d6f15486SAlex Hornung }
654d6f15486SAlex Hornung 
_init_filters(struct cmd_context * cmd,unsigned load_persistent_cache)655d6f15486SAlex Hornung static int _init_filters(struct cmd_context *cmd, unsigned load_persistent_cache)
656d6f15486SAlex Hornung {
657d6f15486SAlex Hornung 	const char *dev_cache = NULL, *cache_dir, *cache_file_prefix;
658d6f15486SAlex Hornung 	struct dev_filter *f3, *f4;
659d6f15486SAlex Hornung 	struct stat st;
660d6f15486SAlex Hornung 	char cache_file[PATH_MAX];
661d6f15486SAlex Hornung 
662d6f15486SAlex Hornung 	cmd->dump_filter = 0;
663d6f15486SAlex Hornung 
664d6f15486SAlex Hornung 	if (!(f3 = _init_filter_components(cmd)))
665d6f15486SAlex Hornung 		return 0;
666d6f15486SAlex Hornung 
667d6f15486SAlex Hornung 	init_ignore_suspended_devices(find_config_tree_int(cmd,
668d6f15486SAlex Hornung 	    "devices/ignore_suspended_devices", DEFAULT_IGNORE_SUSPENDED_DEVICES));
669d6f15486SAlex Hornung 
670d6f15486SAlex Hornung 	/*
671d6f15486SAlex Hornung 	 * If 'cache_dir' or 'cache_file_prefix' is set, ignore 'cache'.
672d6f15486SAlex Hornung 	 */
673d6f15486SAlex Hornung 	cache_dir = find_config_tree_str(cmd, "devices/cache_dir", NULL);
674d6f15486SAlex Hornung 	cache_file_prefix = find_config_tree_str(cmd, "devices/cache_file_prefix", NULL);
675d6f15486SAlex Hornung 
676d6f15486SAlex Hornung 	if (cache_dir || cache_file_prefix) {
677d6f15486SAlex Hornung 		if (dm_snprintf(cache_file, sizeof(cache_file),
678d6f15486SAlex Hornung 		    "%s%s%s/%s.cache",
679d6f15486SAlex Hornung 		    cache_dir ? "" : cmd->system_dir,
680d6f15486SAlex Hornung 		    cache_dir ? "" : "/",
681d6f15486SAlex Hornung 		    cache_dir ? : DEFAULT_CACHE_SUBDIR,
682d6f15486SAlex Hornung 		    cache_file_prefix ? : DEFAULT_CACHE_FILE_PREFIX) < 0) {
683d6f15486SAlex Hornung 			log_error("Persistent cache filename too long.");
684d6f15486SAlex Hornung 			return 0;
685d6f15486SAlex Hornung 		}
686d6f15486SAlex Hornung 	} else if (!(dev_cache = find_config_tree_str(cmd, "devices/cache", NULL)) &&
687d6f15486SAlex Hornung 		   (dm_snprintf(cache_file, sizeof(cache_file),
688d6f15486SAlex Hornung 				"%s/%s/%s.cache",
689d6f15486SAlex Hornung 				cmd->system_dir, DEFAULT_CACHE_SUBDIR,
690d6f15486SAlex Hornung 				DEFAULT_CACHE_FILE_PREFIX) < 0)) {
691d6f15486SAlex Hornung 		log_error("Persistent cache filename too long.");
692d6f15486SAlex Hornung 		return 0;
693d6f15486SAlex Hornung 	}
694d6f15486SAlex Hornung 
695d6f15486SAlex Hornung 	if (!dev_cache)
696d6f15486SAlex Hornung 		dev_cache = cache_file;
697d6f15486SAlex Hornung 
698d6f15486SAlex Hornung 	if (!(f4 = persistent_filter_create(f3, dev_cache))) {
699d6f15486SAlex Hornung 		log_error("Failed to create persistent device filter");
700d6f15486SAlex Hornung 		return 0;
701d6f15486SAlex Hornung 	}
702d6f15486SAlex Hornung 
703d6f15486SAlex Hornung 	/* Should we ever dump persistent filter state? */
704d6f15486SAlex Hornung 	if (find_config_tree_int(cmd, "devices/write_cache_state", 1))
705d6f15486SAlex Hornung 		cmd->dump_filter = 1;
706d6f15486SAlex Hornung 
707d6f15486SAlex Hornung 	if (!*cmd->system_dir)
708d6f15486SAlex Hornung 		cmd->dump_filter = 0;
709d6f15486SAlex Hornung 
710d6f15486SAlex Hornung 	/*
711d6f15486SAlex Hornung 	 * Only load persistent filter device cache on startup if it is newer
712d6f15486SAlex Hornung 	 * than the config file and this is not a long-lived process.
713d6f15486SAlex Hornung 	 */
714d6f15486SAlex Hornung 	if (load_persistent_cache && !cmd->is_long_lived &&
715d6f15486SAlex Hornung 	    !stat(dev_cache, &st) &&
716d6f15486SAlex Hornung 	    (st.st_ctime > config_file_timestamp(cmd->cft)) &&
717d6f15486SAlex Hornung 	    !persistent_filter_load(f4, NULL))
718d6f15486SAlex Hornung 		log_verbose("Failed to load existing device cache from %s",
719d6f15486SAlex Hornung 			    dev_cache);
720d6f15486SAlex Hornung 
721d6f15486SAlex Hornung 	cmd->filter = f4;
722d6f15486SAlex Hornung 
723d6f15486SAlex Hornung 	return 1;
724d6f15486SAlex Hornung }
725d6f15486SAlex Hornung 
_init_formats(struct cmd_context * cmd)726d6f15486SAlex Hornung static int _init_formats(struct cmd_context *cmd)
727d6f15486SAlex Hornung {
728d6f15486SAlex Hornung 	const char *format;
729d6f15486SAlex Hornung 
730d6f15486SAlex Hornung 	struct format_type *fmt;
731d6f15486SAlex Hornung 
732d6f15486SAlex Hornung #ifdef HAVE_LIBDL
733d6f15486SAlex Hornung 	const struct config_node *cn;
734d6f15486SAlex Hornung #endif
735d6f15486SAlex Hornung 
736d6f15486SAlex Hornung 	label_init();
737d6f15486SAlex Hornung 
738d6f15486SAlex Hornung #ifdef LVM1_INTERNAL
739d6f15486SAlex Hornung 	if (!(fmt = init_lvm1_format(cmd)))
740d6f15486SAlex Hornung 		return 0;
741d6f15486SAlex Hornung 	fmt->library = NULL;
742d6f15486SAlex Hornung 	dm_list_add(&cmd->formats, &fmt->list);
743d6f15486SAlex Hornung #endif
744d6f15486SAlex Hornung 
745d6f15486SAlex Hornung #ifdef POOL_INTERNAL
746d6f15486SAlex Hornung 	if (!(fmt = init_pool_format(cmd)))
747d6f15486SAlex Hornung 		return 0;
748d6f15486SAlex Hornung 	fmt->library = NULL;
749d6f15486SAlex Hornung 	dm_list_add(&cmd->formats, &fmt->list);
750d6f15486SAlex Hornung #endif
751d6f15486SAlex Hornung 
752d6f15486SAlex Hornung #ifdef HAVE_LIBDL
753d6f15486SAlex Hornung 	/* Load any formats in shared libs if not static */
754d6f15486SAlex Hornung 	if (!is_static() &&
755d6f15486SAlex Hornung 	    (cn = find_config_tree_node(cmd, "global/format_libraries"))) {
756d6f15486SAlex Hornung 
757d6f15486SAlex Hornung 		struct config_value *cv;
758d6f15486SAlex Hornung 		struct format_type *(*init_format_fn) (struct cmd_context *);
759d6f15486SAlex Hornung 		void *lib;
760d6f15486SAlex Hornung 
761d6f15486SAlex Hornung 		for (cv = cn->v; cv; cv = cv->next) {
762d6f15486SAlex Hornung 			if (cv->type != CFG_STRING) {
763d6f15486SAlex Hornung 				log_error("Invalid string in config file: "
764d6f15486SAlex Hornung 					  "global/format_libraries");
765d6f15486SAlex Hornung 				return 0;
766d6f15486SAlex Hornung 			}
767d6f15486SAlex Hornung 			if (!(lib = load_shared_library(cmd, cv->v.str,
768d6f15486SAlex Hornung 							"format", 0)))
769d6f15486SAlex Hornung 				return_0;
770d6f15486SAlex Hornung 
771d6f15486SAlex Hornung 			if (!(init_format_fn = dlsym(lib, "init_format"))) {
772d6f15486SAlex Hornung 				log_error("Shared library %s does not contain "
773d6f15486SAlex Hornung 					  "format functions", cv->v.str);
774d6f15486SAlex Hornung 				dlclose(lib);
775d6f15486SAlex Hornung 				return 0;
776d6f15486SAlex Hornung 			}
777d6f15486SAlex Hornung 
778d6f15486SAlex Hornung 			if (!(fmt = init_format_fn(cmd)))
779d6f15486SAlex Hornung 				return 0;
780d6f15486SAlex Hornung 			fmt->library = lib;
781d6f15486SAlex Hornung 			dm_list_add(&cmd->formats, &fmt->list);
782d6f15486SAlex Hornung 		}
783d6f15486SAlex Hornung 	}
784d6f15486SAlex Hornung #endif
785d6f15486SAlex Hornung 
786d6f15486SAlex Hornung 	if (!(fmt = create_text_format(cmd)))
787d6f15486SAlex Hornung 		return 0;
788d6f15486SAlex Hornung 	fmt->library = NULL;
789d6f15486SAlex Hornung 	dm_list_add(&cmd->formats, &fmt->list);
790d6f15486SAlex Hornung 
791d6f15486SAlex Hornung 	cmd->fmt_backup = fmt;
792d6f15486SAlex Hornung 
793d6f15486SAlex Hornung 	format = find_config_tree_str(cmd, "global/format",
794d6f15486SAlex Hornung 				 DEFAULT_FORMAT);
795d6f15486SAlex Hornung 
796d6f15486SAlex Hornung 	dm_list_iterate_items(fmt, &cmd->formats) {
797d6f15486SAlex Hornung 		if (!strcasecmp(fmt->name, format) ||
798d6f15486SAlex Hornung 		    (fmt->alias && !strcasecmp(fmt->alias, format))) {
799d6f15486SAlex Hornung 			cmd->default_settings.fmt = fmt;
800d6f15486SAlex Hornung 			cmd->fmt = cmd->default_settings.fmt;
801d6f15486SAlex Hornung 			return 1;
802d6f15486SAlex Hornung 		}
803d6f15486SAlex Hornung 	}
804d6f15486SAlex Hornung 
805d6f15486SAlex Hornung 	log_error("_init_formats: Default format (%s) not found", format);
806d6f15486SAlex Hornung 	return 0;
807d6f15486SAlex Hornung }
808d6f15486SAlex Hornung 
init_lvmcache_orphans(struct cmd_context * cmd)809d6f15486SAlex Hornung int init_lvmcache_orphans(struct cmd_context *cmd)
810d6f15486SAlex Hornung {
811d6f15486SAlex Hornung 	struct format_type *fmt;
812d6f15486SAlex Hornung 
813d6f15486SAlex Hornung 	dm_list_iterate_items(fmt, &cmd->formats)
814d6f15486SAlex Hornung 		if (!lvmcache_add_orphan_vginfo(fmt->orphan_vg_name, fmt))
815d6f15486SAlex Hornung 			return_0;
816d6f15486SAlex Hornung 
817d6f15486SAlex Hornung 	return 1;
818d6f15486SAlex Hornung }
819d6f15486SAlex Hornung 
820d6f15486SAlex Hornung struct segtype_library {
821d6f15486SAlex Hornung 	struct cmd_context *cmd;
822d6f15486SAlex Hornung 	void *lib;
823d6f15486SAlex Hornung 	const char *libname;
824d6f15486SAlex Hornung };
825d6f15486SAlex Hornung 
lvm_register_segtype(struct segtype_library * seglib,struct segment_type * segtype)826d6f15486SAlex Hornung int lvm_register_segtype(struct segtype_library *seglib,
827d6f15486SAlex Hornung 			 struct segment_type *segtype)
828d6f15486SAlex Hornung {
829d6f15486SAlex Hornung 	struct segment_type *segtype2;
830d6f15486SAlex Hornung 
831d6f15486SAlex Hornung 	segtype->library = seglib->lib;
832d6f15486SAlex Hornung 	segtype->cmd = seglib->cmd;
833d6f15486SAlex Hornung 
834d6f15486SAlex Hornung 	dm_list_iterate_items(segtype2, &seglib->cmd->segtypes) {
835d6f15486SAlex Hornung 		if (strcmp(segtype2->name, segtype->name))
836d6f15486SAlex Hornung 			continue;
837d6f15486SAlex Hornung 		log_error("Duplicate segment type %s: "
838d6f15486SAlex Hornung 			  "unloading shared library %s",
839d6f15486SAlex Hornung 			  segtype->name, seglib->libname);
840d6f15486SAlex Hornung 		segtype->ops->destroy(segtype);
841d6f15486SAlex Hornung 		return 0;
842d6f15486SAlex Hornung 	}
843d6f15486SAlex Hornung 
844d6f15486SAlex Hornung 	dm_list_add(&seglib->cmd->segtypes, &segtype->list);
845d6f15486SAlex Hornung 
846d6f15486SAlex Hornung 	return 1;
847d6f15486SAlex Hornung }
848d6f15486SAlex Hornung 
84953d77b81SAlex Hornung #if defined(__NetBSD__) || defined(__DragonFly__)
850d6f15486SAlex Hornung #include <dlfcn.h>
851d6f15486SAlex Hornung #endif
852d6f15486SAlex Hornung 
_init_single_segtype(struct cmd_context * cmd,struct segtype_library * seglib)853d6f15486SAlex Hornung static int _init_single_segtype(struct cmd_context *cmd,
854d6f15486SAlex Hornung 				struct segtype_library *seglib)
855d6f15486SAlex Hornung {
856d6f15486SAlex Hornung 	struct segment_type *(*init_segtype_fn) (struct cmd_context *);
857d6f15486SAlex Hornung 	struct segment_type *segtype;
858d6f15486SAlex Hornung 
859d6f15486SAlex Hornung 	if (!(init_segtype_fn = dlsym(seglib->lib, "init_segtype"))) {
860d6f15486SAlex Hornung 		log_error("Shared library %s does not contain segment type "
861d6f15486SAlex Hornung 			  "functions", seglib->libname);
862d6f15486SAlex Hornung 		return 0;
863d6f15486SAlex Hornung 	}
864d6f15486SAlex Hornung 
865d6f15486SAlex Hornung 	if (!(segtype = init_segtype_fn(seglib->cmd)))
866d6f15486SAlex Hornung 		return_0;
867d6f15486SAlex Hornung 
868d6f15486SAlex Hornung 	return lvm_register_segtype(seglib, segtype);
869d6f15486SAlex Hornung }
870d6f15486SAlex Hornung 
_init_segtypes(struct cmd_context * cmd)871d6f15486SAlex Hornung static int _init_segtypes(struct cmd_context *cmd)
872d6f15486SAlex Hornung {
873d6f15486SAlex Hornung 	struct segment_type *segtype;
874d6f15486SAlex Hornung 	struct segtype_library seglib = { .cmd = cmd };
875d6f15486SAlex Hornung 
876d6f15486SAlex Hornung #ifdef HAVE_LIBDL
877d6f15486SAlex Hornung 	const struct config_node *cn;
878d6f15486SAlex Hornung #endif
879d6f15486SAlex Hornung 
880d6f15486SAlex Hornung 	if (!(segtype = init_striped_segtype(cmd)))
881d6f15486SAlex Hornung 		return 0;
882d6f15486SAlex Hornung 	segtype->library = NULL;
883d6f15486SAlex Hornung 	dm_list_add(&cmd->segtypes, &segtype->list);
884d6f15486SAlex Hornung 
885d6f15486SAlex Hornung 	if (!(segtype = init_zero_segtype(cmd)))
886d6f15486SAlex Hornung 		return 0;
887d6f15486SAlex Hornung 	segtype->library = NULL;
888d6f15486SAlex Hornung 	dm_list_add(&cmd->segtypes, &segtype->list);
889d6f15486SAlex Hornung 
890d6f15486SAlex Hornung 	if (!(segtype = init_error_segtype(cmd)))
891d6f15486SAlex Hornung 		return 0;
892d6f15486SAlex Hornung 	segtype->library = NULL;
893d6f15486SAlex Hornung 	dm_list_add(&cmd->segtypes, &segtype->list);
894d6f15486SAlex Hornung 
895d6f15486SAlex Hornung 	if (!(segtype = init_free_segtype(cmd)))
896d6f15486SAlex Hornung 		return 0;
897d6f15486SAlex Hornung 	segtype->library = NULL;
898d6f15486SAlex Hornung 	dm_list_add(&cmd->segtypes, &segtype->list);
899d6f15486SAlex Hornung 
900d6f15486SAlex Hornung #ifdef SNAPSHOT_INTERNAL
901d6f15486SAlex Hornung 	if (!(segtype = init_snapshot_segtype(cmd)))
902d6f15486SAlex Hornung 		return 0;
903d6f15486SAlex Hornung 	segtype->library = NULL;
904d6f15486SAlex Hornung 	dm_list_add(&cmd->segtypes, &segtype->list);
905d6f15486SAlex Hornung #endif
906d6f15486SAlex Hornung 
907d6f15486SAlex Hornung #ifdef MIRRORED_INTERNAL
908d6f15486SAlex Hornung 	if (!(segtype = init_mirrored_segtype(cmd)))
909d6f15486SAlex Hornung 		return 0;
910d6f15486SAlex Hornung 	segtype->library = NULL;
911d6f15486SAlex Hornung 	dm_list_add(&cmd->segtypes, &segtype->list);
912d6f15486SAlex Hornung #endif
913d6f15486SAlex Hornung 
914d6f15486SAlex Hornung #ifdef HAVE_LIBDL
915d6f15486SAlex Hornung 	/* Load any formats in shared libs unless static */
916d6f15486SAlex Hornung 	if (!is_static() &&
917d6f15486SAlex Hornung 	    (cn = find_config_tree_node(cmd, "global/segment_libraries"))) {
918d6f15486SAlex Hornung 
919d6f15486SAlex Hornung 		struct config_value *cv;
920d6f15486SAlex Hornung 		int (*init_multiple_segtypes_fn) (struct cmd_context *,
921d6f15486SAlex Hornung 						  struct segtype_library *);
922d6f15486SAlex Hornung 
923d6f15486SAlex Hornung 		for (cv = cn->v; cv; cv = cv->next) {
924d6f15486SAlex Hornung 			if (cv->type != CFG_STRING) {
925d6f15486SAlex Hornung 				log_error("Invalid string in config file: "
926d6f15486SAlex Hornung 					  "global/segment_libraries");
927d6f15486SAlex Hornung 				return 0;
928d6f15486SAlex Hornung 			}
929d6f15486SAlex Hornung 			seglib.libname = cv->v.str;
930d6f15486SAlex Hornung 			if (!(seglib.lib = load_shared_library(cmd,
931d6f15486SAlex Hornung 							seglib.libname,
932d6f15486SAlex Hornung 							"segment type", 0)))
933d6f15486SAlex Hornung 				return_0;
934d6f15486SAlex Hornung 
935d6f15486SAlex Hornung 			if ((init_multiple_segtypes_fn =
936d6f15486SAlex Hornung 			    dlsym(seglib.lib, "init_multiple_segtypes"))) {
937d6f15486SAlex Hornung 				if (dlsym(seglib.lib, "init_segtype"))
938d6f15486SAlex Hornung 					log_warn("WARNING: Shared lib %s has "
939d6f15486SAlex Hornung 						 "conflicting init fns.  Using"
940d6f15486SAlex Hornung 						 " init_multiple_segtypes().",
941d6f15486SAlex Hornung 						 seglib.libname);
942d6f15486SAlex Hornung 			} else
943d6f15486SAlex Hornung 				init_multiple_segtypes_fn =
944d6f15486SAlex Hornung 				    _init_single_segtype;
945d6f15486SAlex Hornung 
946d6f15486SAlex Hornung 			if (!init_multiple_segtypes_fn(cmd, &seglib)) {
947d6f15486SAlex Hornung 				struct dm_list *sgtl, *tmp;
948d6f15486SAlex Hornung 				log_error("init_multiple_segtypes() failed: "
949d6f15486SAlex Hornung 					  "Unloading shared library %s",
950d6f15486SAlex Hornung 					  seglib.libname);
951d6f15486SAlex Hornung 				dm_list_iterate_safe(sgtl, tmp, &cmd->segtypes) {
952d6f15486SAlex Hornung 					segtype = dm_list_item(sgtl, struct segment_type);
953d6f15486SAlex Hornung 					if (segtype->library == seglib.lib) {
954d6f15486SAlex Hornung 						dm_list_del(&segtype->list);
955d6f15486SAlex Hornung 						segtype->ops->destroy(segtype);
956d6f15486SAlex Hornung 					}
957d6f15486SAlex Hornung 				}
958d6f15486SAlex Hornung 				dlclose(seglib.lib);
959d6f15486SAlex Hornung 				return_0;
960d6f15486SAlex Hornung 			}
961d6f15486SAlex Hornung 		}
962d6f15486SAlex Hornung 	}
963d6f15486SAlex Hornung #endif
964d6f15486SAlex Hornung 
965d6f15486SAlex Hornung 	return 1;
966d6f15486SAlex Hornung }
967d6f15486SAlex Hornung 
_init_hostname(struct cmd_context * cmd)968d6f15486SAlex Hornung static int _init_hostname(struct cmd_context *cmd)
969d6f15486SAlex Hornung {
970d6f15486SAlex Hornung 	struct utsname uts;
971d6f15486SAlex Hornung 
972d6f15486SAlex Hornung 	if (uname(&uts)) {
973d6f15486SAlex Hornung 		log_sys_error("uname", "_init_hostname");
974d6f15486SAlex Hornung 		return 0;
975d6f15486SAlex Hornung 	}
976d6f15486SAlex Hornung 
977d6f15486SAlex Hornung 	if (!(cmd->hostname = dm_pool_strdup(cmd->libmem, uts.nodename))) {
978d6f15486SAlex Hornung 		log_error("_init_hostname: dm_pool_strdup failed");
979d6f15486SAlex Hornung 		return 0;
980d6f15486SAlex Hornung 	}
981d6f15486SAlex Hornung 
982d6f15486SAlex Hornung 	if (!(cmd->kernel_vsn = dm_pool_strdup(cmd->libmem, uts.release))) {
983d6f15486SAlex Hornung 		log_error("_init_hostname: dm_pool_strdup kernel_vsn failed");
984d6f15486SAlex Hornung 		return 0;
985d6f15486SAlex Hornung 	}
986d6f15486SAlex Hornung 
987d6f15486SAlex Hornung 	return 1;
988d6f15486SAlex Hornung }
989d6f15486SAlex Hornung 
_init_backup(struct cmd_context * cmd)990d6f15486SAlex Hornung static int _init_backup(struct cmd_context *cmd)
991d6f15486SAlex Hornung {
992d6f15486SAlex Hornung 	uint32_t days, min;
993d6f15486SAlex Hornung 	char default_dir[PATH_MAX];
994d6f15486SAlex Hornung 	const char *dir;
995d6f15486SAlex Hornung 
996d6f15486SAlex Hornung 	if (!cmd->system_dir) {
997d6f15486SAlex Hornung 		log_warn("WARNING: Metadata changes will NOT be backed up");
998d6f15486SAlex Hornung 		backup_init(cmd, "", 0);
999d6f15486SAlex Hornung 		archive_init(cmd, "", 0, 0, 0);
1000d6f15486SAlex Hornung 		return 1;
1001d6f15486SAlex Hornung 	}
1002d6f15486SAlex Hornung 
1003d6f15486SAlex Hornung 	/* set up archiving */
1004d6f15486SAlex Hornung 	cmd->default_settings.archive =
1005d6f15486SAlex Hornung 	    find_config_tree_bool(cmd, "backup/archive",
1006d6f15486SAlex Hornung 			     DEFAULT_ARCHIVE_ENABLED);
1007d6f15486SAlex Hornung 
1008d6f15486SAlex Hornung 	days = (uint32_t) find_config_tree_int(cmd, "backup/retain_days",
1009d6f15486SAlex Hornung 					  DEFAULT_ARCHIVE_DAYS);
1010d6f15486SAlex Hornung 
1011d6f15486SAlex Hornung 	min = (uint32_t) find_config_tree_int(cmd, "backup/retain_min",
1012d6f15486SAlex Hornung 					 DEFAULT_ARCHIVE_NUMBER);
1013d6f15486SAlex Hornung 
1014d6f15486SAlex Hornung 	if (dm_snprintf
1015d6f15486SAlex Hornung 	    (default_dir, sizeof(default_dir), "%s/%s", cmd->system_dir,
1016d6f15486SAlex Hornung 	     DEFAULT_ARCHIVE_SUBDIR) == -1) {
1017d6f15486SAlex Hornung 		log_error("Couldn't create default archive path '%s/%s'.",
1018d6f15486SAlex Hornung 			  cmd->system_dir, DEFAULT_ARCHIVE_SUBDIR);
1019d6f15486SAlex Hornung 		return 0;
1020d6f15486SAlex Hornung 	}
1021d6f15486SAlex Hornung 
1022d6f15486SAlex Hornung 	dir = find_config_tree_str(cmd, "backup/archive_dir",
1023d6f15486SAlex Hornung 			      default_dir);
1024d6f15486SAlex Hornung 
1025d6f15486SAlex Hornung 	if (!archive_init(cmd, dir, days, min,
1026d6f15486SAlex Hornung 			  cmd->default_settings.archive)) {
1027d6f15486SAlex Hornung 		log_debug("archive_init failed.");
1028d6f15486SAlex Hornung 		return 0;
1029d6f15486SAlex Hornung 	}
1030d6f15486SAlex Hornung 
1031d6f15486SAlex Hornung 	/* set up the backup */
1032d6f15486SAlex Hornung 	cmd->default_settings.backup =
1033d6f15486SAlex Hornung 	    find_config_tree_bool(cmd, "backup/backup",
1034d6f15486SAlex Hornung 			     DEFAULT_BACKUP_ENABLED);
1035d6f15486SAlex Hornung 
1036d6f15486SAlex Hornung 	if (dm_snprintf
1037d6f15486SAlex Hornung 	    (default_dir, sizeof(default_dir), "%s/%s", cmd->system_dir,
1038d6f15486SAlex Hornung 	     DEFAULT_BACKUP_SUBDIR) == -1) {
1039d6f15486SAlex Hornung 		log_error("Couldn't create default backup path '%s/%s'.",
1040d6f15486SAlex Hornung 			  cmd->system_dir, DEFAULT_BACKUP_SUBDIR);
1041d6f15486SAlex Hornung 		return 0;
1042d6f15486SAlex Hornung 	}
1043d6f15486SAlex Hornung 
1044d6f15486SAlex Hornung 	dir = find_config_tree_str(cmd, "backup/backup_dir", default_dir);
1045d6f15486SAlex Hornung 
1046d6f15486SAlex Hornung 	if (!backup_init(cmd, dir, cmd->default_settings.backup)) {
1047d6f15486SAlex Hornung 		log_debug("backup_init failed.");
1048d6f15486SAlex Hornung 		return 0;
1049d6f15486SAlex Hornung 	}
1050d6f15486SAlex Hornung 
1051d6f15486SAlex Hornung 	return 1;
1052d6f15486SAlex Hornung }
1053d6f15486SAlex Hornung 
_init_rand(struct cmd_context * cmd)1054d6f15486SAlex Hornung static void _init_rand(struct cmd_context *cmd)
1055d6f15486SAlex Hornung {
1056d6f15486SAlex Hornung 	if (read_urandom(&cmd->rand_seed, sizeof(cmd->rand_seed)))
1057d6f15486SAlex Hornung 		return;
1058d6f15486SAlex Hornung 
1059d6f15486SAlex Hornung 	cmd->rand_seed = (unsigned) time(NULL) + (unsigned) getpid();
1060d6f15486SAlex Hornung }
1061d6f15486SAlex Hornung 
_init_globals(struct cmd_context * cmd)1062d6f15486SAlex Hornung static void _init_globals(struct cmd_context *cmd)
1063d6f15486SAlex Hornung {
1064d6f15486SAlex Hornung 	init_full_scan_done(0);
1065d6f15486SAlex Hornung 	init_mirror_in_sync(0);
1066d6f15486SAlex Hornung 
1067d6f15486SAlex Hornung }
1068d6f15486SAlex Hornung 
1069d6f15486SAlex Hornung /* Entry point */
create_toolcontext(unsigned is_long_lived,const char * system_dir)1070d6f15486SAlex Hornung struct cmd_context *create_toolcontext(unsigned is_long_lived,
1071d6f15486SAlex Hornung 				       const char *system_dir)
1072d6f15486SAlex Hornung {
1073d6f15486SAlex Hornung 	struct cmd_context *cmd;
1074d6f15486SAlex Hornung 
1075d6f15486SAlex Hornung #ifdef M_MMAP_MAX
1076d6f15486SAlex Hornung 	mallopt(M_MMAP_MAX, 0);
1077d6f15486SAlex Hornung #endif
1078d6f15486SAlex Hornung 
1079d6f15486SAlex Hornung 	if (!setlocale(LC_ALL, ""))
1080d6f15486SAlex Hornung 		log_very_verbose("setlocale failed");
1081d6f15486SAlex Hornung 
1082d6f15486SAlex Hornung #ifdef INTL_PACKAGE
1083d6f15486SAlex Hornung 	bindtextdomain(INTL_PACKAGE, LOCALEDIR);
1084d6f15486SAlex Hornung #endif
1085d6f15486SAlex Hornung 
1086d6f15486SAlex Hornung 	init_syslog(DEFAULT_LOG_FACILITY);
1087d6f15486SAlex Hornung 
1088d6f15486SAlex Hornung 	if (!(cmd = dm_malloc(sizeof(*cmd)))) {
1089d6f15486SAlex Hornung 		log_error("Failed to allocate command context");
1090d6f15486SAlex Hornung 		return NULL;
1091d6f15486SAlex Hornung 	}
1092d6f15486SAlex Hornung 	memset(cmd, 0, sizeof(*cmd));
1093d6f15486SAlex Hornung 	cmd->is_long_lived = is_long_lived;
1094d6f15486SAlex Hornung 	cmd->handles_missing_pvs = 0;
1095d6f15486SAlex Hornung 	cmd->handles_unknown_segments = 0;
1096d6f15486SAlex Hornung 	cmd->hosttags = 0;
1097d6f15486SAlex Hornung 	dm_list_init(&cmd->formats);
1098d6f15486SAlex Hornung 	dm_list_init(&cmd->segtypes);
1099d6f15486SAlex Hornung 	dm_list_init(&cmd->tags);
1100d6f15486SAlex Hornung 	dm_list_init(&cmd->config_files);
1101d6f15486SAlex Hornung 
1102d6f15486SAlex Hornung 	/* FIXME Make this configurable? */
1103d6f15486SAlex Hornung 	reset_lvm_errno(1);
1104d6f15486SAlex Hornung 
1105d6f15486SAlex Hornung 	/*
1106d6f15486SAlex Hornung 	 * Environment variable LVM_SYSTEM_DIR overrides this below.
1107d6f15486SAlex Hornung 	 */
1108d6f15486SAlex Hornung         if (system_dir)
1109d6f15486SAlex Hornung 		strncpy(cmd->system_dir, system_dir, sizeof(cmd->system_dir) - 1);
1110d6f15486SAlex Hornung 	else
1111d6f15486SAlex Hornung 		strcpy(cmd->system_dir, DEFAULT_SYS_DIR);
1112d6f15486SAlex Hornung 
1113d6f15486SAlex Hornung 	if (!_get_env_vars(cmd))
1114d6f15486SAlex Hornung 		goto_out;
1115d6f15486SAlex Hornung 
1116d6f15486SAlex Hornung 	/* Create system directory if it doesn't already exist */
1117d6f15486SAlex Hornung 	if (*cmd->system_dir && !dm_create_dir(cmd->system_dir)) {
1118d6f15486SAlex Hornung 		log_error("Failed to create LVM2 system dir for metadata backups, config "
1119d6f15486SAlex Hornung 			  "files and internal cache.");
1120d6f15486SAlex Hornung 		log_error("Set environment variable LVM_SYSTEM_DIR to alternative location "
1121d6f15486SAlex Hornung 			  "or empty string.");
1122d6f15486SAlex Hornung 		goto out;
1123d6f15486SAlex Hornung 	}
1124d6f15486SAlex Hornung 
1125d6f15486SAlex Hornung 	if (!(cmd->libmem = dm_pool_create("library", 4 * 1024))) {
1126d6f15486SAlex Hornung 		log_error("Library memory pool creation failed");
1127d6f15486SAlex Hornung 		goto out;
1128d6f15486SAlex Hornung 	}
1129d6f15486SAlex Hornung 
1130d6f15486SAlex Hornung 	if (!_init_lvm_conf(cmd))
1131d6f15486SAlex Hornung 		goto_out;
1132d6f15486SAlex Hornung 
1133d6f15486SAlex Hornung 	_init_logging(cmd);
1134d6f15486SAlex Hornung 
1135d6f15486SAlex Hornung 	if (!_init_hostname(cmd))
1136d6f15486SAlex Hornung 		goto_out;
1137d6f15486SAlex Hornung 
1138d6f15486SAlex Hornung 	if (!_init_tags(cmd, cmd->cft))
1139d6f15486SAlex Hornung 		goto_out;
1140d6f15486SAlex Hornung 
1141d6f15486SAlex Hornung 	if (!_init_tag_configs(cmd))
1142d6f15486SAlex Hornung 		goto_out;
1143d6f15486SAlex Hornung 
1144d6f15486SAlex Hornung 	if (!_merge_config_files(cmd))
1145d6f15486SAlex Hornung 		goto_out;
1146d6f15486SAlex Hornung 
1147d6f15486SAlex Hornung 	if (!_process_config(cmd))
1148d6f15486SAlex Hornung 		goto_out;
1149d6f15486SAlex Hornung 
1150d6f15486SAlex Hornung 	if (!_init_dev_cache(cmd))
1151d6f15486SAlex Hornung 		goto_out;
1152d6f15486SAlex Hornung 
1153d6f15486SAlex Hornung 	if (!_init_filters(cmd, 1))
1154d6f15486SAlex Hornung 		goto_out;
1155d6f15486SAlex Hornung 
1156d6f15486SAlex Hornung 	if (!(cmd->mem = dm_pool_create("command", 4 * 1024))) {
1157d6f15486SAlex Hornung 		log_error("Command memory pool creation failed");
1158d6f15486SAlex Hornung 		goto out;
1159d6f15486SAlex Hornung 	}
1160d6f15486SAlex Hornung 
1161d6f15486SAlex Hornung 	memlock_init(cmd);
1162d6f15486SAlex Hornung 
1163d6f15486SAlex Hornung 	if (!_init_formats(cmd))
1164d6f15486SAlex Hornung 		goto_out;
1165d6f15486SAlex Hornung 
1166d6f15486SAlex Hornung 	if (!init_lvmcache_orphans(cmd))
1167d6f15486SAlex Hornung 		goto_out;
1168d6f15486SAlex Hornung 
1169d6f15486SAlex Hornung 	if (!_init_segtypes(cmd))
1170d6f15486SAlex Hornung 		goto_out;
1171d6f15486SAlex Hornung 
1172d6f15486SAlex Hornung 	if (!_init_backup(cmd))
1173d6f15486SAlex Hornung 		goto_out;
1174d6f15486SAlex Hornung 
1175d6f15486SAlex Hornung 	_init_rand(cmd);
1176d6f15486SAlex Hornung 
1177d6f15486SAlex Hornung 	_init_globals(cmd);
1178d6f15486SAlex Hornung 
1179d6f15486SAlex Hornung 	cmd->default_settings.cache_vgmetadata = 1;
1180d6f15486SAlex Hornung 	cmd->current_settings = cmd->default_settings;
1181d6f15486SAlex Hornung 
1182d6f15486SAlex Hornung 	cmd->config_valid = 1;
1183d6f15486SAlex Hornung out:
1184d6f15486SAlex Hornung 	return cmd;
1185d6f15486SAlex Hornung }
1186d6f15486SAlex Hornung 
_destroy_formats(struct dm_list * formats)1187d6f15486SAlex Hornung static void _destroy_formats(struct dm_list *formats)
1188d6f15486SAlex Hornung {
1189d6f15486SAlex Hornung 	struct dm_list *fmtl, *tmp;
1190d6f15486SAlex Hornung 	struct format_type *fmt;
1191d6f15486SAlex Hornung 	void *lib;
1192d6f15486SAlex Hornung 
1193d6f15486SAlex Hornung 	dm_list_iterate_safe(fmtl, tmp, formats) {
1194d6f15486SAlex Hornung 		fmt = dm_list_item(fmtl, struct format_type);
1195d6f15486SAlex Hornung 		dm_list_del(&fmt->list);
1196d6f15486SAlex Hornung 		lib = fmt->library;
1197d6f15486SAlex Hornung 		fmt->ops->destroy(fmt);
1198d6f15486SAlex Hornung #ifdef HAVE_LIBDL
1199d6f15486SAlex Hornung 		if (lib)
1200d6f15486SAlex Hornung 			dlclose(lib);
1201d6f15486SAlex Hornung #endif
1202d6f15486SAlex Hornung 	}
1203d6f15486SAlex Hornung }
1204d6f15486SAlex Hornung 
_destroy_segtypes(struct dm_list * segtypes)1205d6f15486SAlex Hornung static void _destroy_segtypes(struct dm_list *segtypes)
1206d6f15486SAlex Hornung {
1207d6f15486SAlex Hornung 	struct dm_list *sgtl, *tmp;
1208d6f15486SAlex Hornung 	struct segment_type *segtype;
1209d6f15486SAlex Hornung 	void *lib;
1210d6f15486SAlex Hornung 
1211d6f15486SAlex Hornung 	dm_list_iterate_safe(sgtl, tmp, segtypes) {
1212d6f15486SAlex Hornung 		segtype = dm_list_item(sgtl, struct segment_type);
1213d6f15486SAlex Hornung 		dm_list_del(&segtype->list);
1214d6f15486SAlex Hornung 		lib = segtype->library;
1215d6f15486SAlex Hornung 		segtype->ops->destroy(segtype);
1216d6f15486SAlex Hornung #ifdef HAVE_LIBDL
1217d6f15486SAlex Hornung 		/*
1218d6f15486SAlex Hornung 		 * If no segtypes remain from this library, close it.
1219d6f15486SAlex Hornung 		 */
1220d6f15486SAlex Hornung 		if (lib) {
1221d6f15486SAlex Hornung 			struct segment_type *segtype2;
1222d6f15486SAlex Hornung 			dm_list_iterate_items(segtype2, segtypes)
1223d6f15486SAlex Hornung 				if (segtype2->library == lib)
1224d6f15486SAlex Hornung 					goto skip_dlclose;
1225d6f15486SAlex Hornung 			dlclose(lib);
1226d6f15486SAlex Hornung skip_dlclose:
1227d6f15486SAlex Hornung 			;
1228d6f15486SAlex Hornung 		}
1229d6f15486SAlex Hornung #endif
1230d6f15486SAlex Hornung 	}
1231d6f15486SAlex Hornung }
1232d6f15486SAlex Hornung 
refresh_filters(struct cmd_context * cmd)1233d6f15486SAlex Hornung int refresh_filters(struct cmd_context *cmd)
1234d6f15486SAlex Hornung {
1235d6f15486SAlex Hornung 	if (cmd->filter) {
1236d6f15486SAlex Hornung 		cmd->filter->destroy(cmd->filter);
1237d6f15486SAlex Hornung 		cmd->filter = NULL;
1238d6f15486SAlex Hornung 	}
1239d6f15486SAlex Hornung 
1240d6f15486SAlex Hornung 	return _init_filters(cmd, 0);
1241d6f15486SAlex Hornung }
1242d6f15486SAlex Hornung 
refresh_toolcontext(struct cmd_context * cmd)1243d6f15486SAlex Hornung int refresh_toolcontext(struct cmd_context *cmd)
1244d6f15486SAlex Hornung {
1245d6f15486SAlex Hornung 	log_verbose("Reloading config files");
1246d6f15486SAlex Hornung 
1247d6f15486SAlex Hornung 	/*
1248d6f15486SAlex Hornung 	 * Don't update the persistent filter cache as we will
1249d6f15486SAlex Hornung 	 * perform a full rescan.
1250d6f15486SAlex Hornung 	 */
1251d6f15486SAlex Hornung 
1252d6f15486SAlex Hornung 	activation_release();
1253d6f15486SAlex Hornung 	lvmcache_destroy(cmd, 0);
1254d6f15486SAlex Hornung 	label_exit();
1255d6f15486SAlex Hornung 	_destroy_segtypes(&cmd->segtypes);
1256d6f15486SAlex Hornung 	_destroy_formats(&cmd->formats);
1257d6f15486SAlex Hornung 	if (cmd->filter) {
1258d6f15486SAlex Hornung 		cmd->filter->destroy(cmd->filter);
1259d6f15486SAlex Hornung 		cmd->filter = NULL;
1260d6f15486SAlex Hornung 	}
1261d6f15486SAlex Hornung 	dev_cache_exit();
1262d6f15486SAlex Hornung 	_destroy_tags(cmd);
1263d6f15486SAlex Hornung 	_destroy_tag_configs(cmd);
1264d6f15486SAlex Hornung 
1265d6f15486SAlex Hornung 	cmd->config_valid = 0;
1266d6f15486SAlex Hornung 
1267d6f15486SAlex Hornung 	cmd->hosttags = 0;
1268d6f15486SAlex Hornung 
1269d6f15486SAlex Hornung 	if (!_init_lvm_conf(cmd))
1270d6f15486SAlex Hornung 		return 0;
1271d6f15486SAlex Hornung 
1272d6f15486SAlex Hornung 	_init_logging(cmd);
1273d6f15486SAlex Hornung 
1274d6f15486SAlex Hornung 	if (!_init_tags(cmd, cmd->cft))
1275d6f15486SAlex Hornung 		return 0;
1276d6f15486SAlex Hornung 
1277d6f15486SAlex Hornung 	if (!_init_tag_configs(cmd))
1278d6f15486SAlex Hornung 		return 0;
1279d6f15486SAlex Hornung 
1280d6f15486SAlex Hornung 	if (!_merge_config_files(cmd))
1281d6f15486SAlex Hornung 		return 0;
1282d6f15486SAlex Hornung 
1283d6f15486SAlex Hornung 	if (!_process_config(cmd))
1284d6f15486SAlex Hornung 		return 0;
1285d6f15486SAlex Hornung 
1286d6f15486SAlex Hornung 	if (!_init_dev_cache(cmd))
1287d6f15486SAlex Hornung 		return 0;
1288d6f15486SAlex Hornung 
1289d6f15486SAlex Hornung 	if (!_init_filters(cmd, 0))
1290d6f15486SAlex Hornung 		return 0;
1291d6f15486SAlex Hornung 
1292d6f15486SAlex Hornung 	if (!_init_formats(cmd))
1293d6f15486SAlex Hornung 		return 0;
1294d6f15486SAlex Hornung 
1295d6f15486SAlex Hornung 	if (!init_lvmcache_orphans(cmd))
1296d6f15486SAlex Hornung 		return 0;
1297d6f15486SAlex Hornung 
1298d6f15486SAlex Hornung 	if (!_init_segtypes(cmd))
1299d6f15486SAlex Hornung 		return 0;
1300d6f15486SAlex Hornung 
1301d6f15486SAlex Hornung 	cmd->config_valid = 1;
1302d6f15486SAlex Hornung 
1303d6f15486SAlex Hornung 	reset_lvm_errno(1);
1304d6f15486SAlex Hornung 	return 1;
1305d6f15486SAlex Hornung }
1306d6f15486SAlex Hornung 
destroy_toolcontext(struct cmd_context * cmd)1307d6f15486SAlex Hornung void destroy_toolcontext(struct cmd_context *cmd)
1308d6f15486SAlex Hornung {
1309d6f15486SAlex Hornung 	if (cmd->dump_filter)
1310d6f15486SAlex Hornung 		persistent_filter_dump(cmd->filter);
1311d6f15486SAlex Hornung 
1312d6f15486SAlex Hornung 	archive_exit(cmd);
1313d6f15486SAlex Hornung 	backup_exit(cmd);
1314d6f15486SAlex Hornung 	lvmcache_destroy(cmd, 0);
1315d6f15486SAlex Hornung 	label_exit();
1316d6f15486SAlex Hornung 	_destroy_segtypes(&cmd->segtypes);
1317d6f15486SAlex Hornung 	_destroy_formats(&cmd->formats);
1318d6f15486SAlex Hornung 	if (cmd->filter)
1319d6f15486SAlex Hornung 		cmd->filter->destroy(cmd->filter);
1320d6f15486SAlex Hornung 	if (cmd->mem)
1321d6f15486SAlex Hornung 		dm_pool_destroy(cmd->mem);
1322d6f15486SAlex Hornung 	dev_cache_exit();
1323d6f15486SAlex Hornung 	_destroy_tags(cmd);
1324d6f15486SAlex Hornung 	_destroy_tag_configs(cmd);
1325d6f15486SAlex Hornung 	if (cmd->libmem)
1326d6f15486SAlex Hornung 		dm_pool_destroy(cmd->libmem);
1327d6f15486SAlex Hornung 	dm_free(cmd);
1328d6f15486SAlex Hornung 
1329d6f15486SAlex Hornung 	release_log_memory();
1330d6f15486SAlex Hornung 	activation_exit();
1331d6f15486SAlex Hornung 	fin_log();
1332d6f15486SAlex Hornung 	fin_syslog();
1333d6f15486SAlex Hornung 	reset_lvm_errno(0);
1334d6f15486SAlex Hornung }
1335