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